(function (angular) {
    angular.module('ui.grid')
        .constant("GridConstants", {
            NOTIFY_HIDE_COLUMN: 'hide_column',
            NOTIFY_COLLPASE_LEFT_MENU: 'collpase_left_menu',
            MULTI_PAGE_SELECT_MAX: 500
        })
        .provider('gridService', gridServiceProvider)
        .service('uiGridOperationService', uiGridOperationService)
        .directive('uiGridCustomerColumnResizer', uiGridCustomerColumnResizer)
        .directive('uiGridMenuCustomerButton', uiGridMenuCustomerButton)
        .directive('uiGridCustomerMenuItem', uiGridCustomerMenuItem)
        .directive('uiGridCustomerAutoResize', uiGridCustomerAutoResize)
        .directive('uiGridCustomerPagination', uiGridCustomerPagination)
        .directive('uiGridOperation', uiGridOperation)
        .directive('uiGridOperationRowHeaderButtons', uiGridOperationRowHeaderButtons)
        .directive('uiGridOperationHeaderButtons', uiGridOperationHeaderButtons)
        .directive('uiGridEolOperation', uiGridEolOperation)
        .directive('uiGridCustomerScrollbar', uiGridCustomerScrollbar)
        .run(uiGridOperationTemplates);

    gridServiceProvider.$inject = ['uiGridConstants'];
    function gridServiceProvider(uiGridConstants) {
        var provider = this, supportMultiPageSelectAll = false;
        provider.innerGridOptions = {
            headerRowHeight: 33,
            rowHeight: 33,
            minRowsToShow: 1,
            maxRowsToShow: 100,
            gridFooterHeight: 22,
            enableGridMenu: false,
            showGridFooter: false,
            showColumnFooter: false,
            enableSorting: false,
            useExternalSorting: true,
            enableFiltering: false,
            enableColumnMoving: true,
            enableColumnMenus: false,
            enableHorizontalScrollbar: uiGridConstants.scrollbars.WHEN_NEEDED,
            enableVerticalScrollbar: uiGridConstants.scrollbars.NEVER,
            virtualizationThreshold: 100,
            columnVirtualizationThreshold: 30,

            enablePagination: false,
            enablePaginationControls: false,
            useExternalPagination: false,
            useCustomPagination: false,
            paginationPageSizes: [10, 20, 30, 50],
            paginationPageSize: 10,
            paginationCurrentPage: 1,

            enableRowSelection: false,
            multiSelect: false,
            multiPageSelect: false,
            noUnselect: false,
            modifierKeysToMultiSelect: false,
            enableRowHeaderSelection: false,
            enableFullRowSelection: false,
            enableSelectAll: true,

            enableOperation: false,
            enableOperationRemoveSelected: false,
            enableEolOperation: false,

            enableColumnResizing: true,
            enableAutoResize: 1,

            treeRowHeaderAlwaysVisible: false,
            enableGrouping: false,
            groupingShowCounts: false,
            // groupingNullLabel : ,
            enableGroupHeaderSelection: false,
            isRowSelectable: function (row) {
                if (row.groupHeader) {
                    return false;
                }
                return true;
            }
        };

        provider.defaultGridOptions = {
            headerRowHeight: 33,
            rowHeight: 33,
            minRowsToShow: 1,
            maxRowsToShow: 100,
            enableGridMenu: false,
            showGridFooter: false,
            showColumnFooter: false,
            enableSorting: true,
            gridFooterHeight: 22,
            useExternalSorting: true,
            enableFiltering: false,
            enableColumnMoving: true,
            enableColumnMenus: false,
            enableHorizontalScrollbar: uiGridConstants.scrollbars.WHEN_NEEDED,
            enableVerticalScrollbar: uiGridConstants.scrollbars.NEVER,
            virtualizationThreshold: 100,
            columnVirtualizationThreshold: 30,

            enablePagination: true,
            enablePaginationControls: true,
            useExternalPagination: true,
            useCustomPagination: false,
            paginationPageSizes: [10, 20, 30, 50],
            paginationPageSize: 10,
            paginationCurrentPage: 1,

            enableRowSelection: true,
            multiSelect: false,
            multiPageSelect: false,
            noUnselect: false,
            modifierKeysToMultiSelect: false,
            enableRowHeaderSelection: true,
            enableFullRowSelection: true,
            enableSelectAll: true,

            enableOperation: false,
            enableOperationRemoveSelected: false,
            enableEolOperation: false,

            enableColumnResizing: true,
            enableAutoResize: 1,

            treeRowHeaderAlwaysVisible: false,
            enableGrouping: false,
            groupingShowCounts: false,
            // groupingNullLabel : ,
            enableGroupHeaderSelection: false,
            isRowSelectable: function (row) {
                if (row.groupHeader) {
                    return false;
                }
                return true;
            },
            pageNoKeydown: function (e) {
                var evt = window.event || e;
                var keyCode = evt.which ? evt.which : evt.keyCode;
                // enter key Code
                if (keyCode == 13) {
                    if (evt.preventDefault)
                        evt.preventDefault();
                    if (evt.stopPropagation)
                        evt.stopPropagation();
                    evt.returnValue = false;
                }
            }

            // exporterMenuCsv : false,
            // exporterMenuPdf : false,
            // exporterSuppressMenu : false,
            // exporterMenuAllData : false,
            // exporterMenuVisibleData : true,
            // exporterMenuSelectedData : true,
            // exporterMenuLabel : 'Export',
            // exporterSuppressColumns : [],
            // exporterCsvColumnSeparator : ',',
            // exporterFieldCallback : function(grid, row, col, value) {
            // return value;
            // },
            // exporterHeaderFilter : function(displayName) {
            // return displayName;
            // },
            // exporterHeaderFilterUseName : true,
            // exporterOlderExcelCompatibility : false,
            // exporterCsvFilename : 'download.csv',
            // exporterPdfFilename : 'download.pdf'
        };

        provider.fsGridTemplate = '<div fs-grid ng-model=\"row.entity\" fs-ui-grid=\"grid\" fs-ui-grid-row=\"row\" fs-ui-grid-col=\"col\" fs-grid-config=\"col.colDef\" fs-verify-model="row.grid.options.verifyData" fs-validator-config=\"col.colDef.validatorConfig\"></div>';
        this.$get = gridServiceGet;
        gridServiceGet.$inject = ['$rootScope', '$translate', '$q', '$timeout', 'uiGridConstants', 'i18nService', 'loggerFactory', 'storageService', 'modalService'];
        function gridServiceGet($rootScope, $translate, $q, $timeout, uiGridConstants, i18nService, loggerFactory, storageService, modalService) {
            var log = loggerFactory.getLogger("gridService");
            function removeRows($scope, selectedRows, apiBoundName) {
                if (!selectedRows || selectedRows.length == 0) {
                    return;
                }
                apiBoundName = apiBoundName || 'gridApi';
                var allRows = angular.isString($scope[apiBoundName].grid.options.data) ? $scope.$eval($scope[apiBoundName].grid.options.data) : $scope[apiBoundName].grid.options.data;
                angular.forEach(selectedRows, function (row) {
                    $scope[apiBoundName].selection.unSelectRow(row);
                });
                angular.forEach(selectedRows, function (selectedRow) {
                    removeItem(allRows, selectedRow);
                });
            }
            function removeSelectedRows($scope, apiBoundName) {
                apiBoundName = apiBoundName || 'gridApi';
                var selectedRows = $scope[apiBoundName].selection.getSelectedRows();
                removeRows($scope, selectedRows, apiBoundName);
            }
            function removeItem(items, item) {
                angular.forEach(items, function (row, index) {
                    if (row.$$hashKey == item.$$hashKey) {
                        items.splice(index, 1);
                    }
                });
            }
            function createInnerGridOptions($scope, tableConfig, rowSelectionChanged, sortChanged, apiBoundName) {
                var options = angular.copy(provider.innerGridOptions);
                var tableSetting = storageService.getTableSetting($scope.$state.current.name + ':' + tableConfig.name);
                options.name = tableConfig.name;
                apiBoundName = apiBoundName || tableConfig.apiBoundName || 'gridApi';
                // i18nService.setCurrentLang($rootScope.I18N.language);
                i18nService.setCurrentLang('en');
                // options.gridMenuTitleFilter = $translate;
                prepareColumnDefs($scope, tableConfig, options, tableSetting);
                options.columnDefs = tableConfig.columnDefs || [];
				/*if (options.enableVerticalScrollbar == uiGridConstants.scrollbars.NEVER && options.columnDefs.length > 0) {
					options.columnDefs[options.columnDefs.length - 1].pinnedRight = true;
				}*/
                options.onRegisterApi = function (gridApi) {
                    $scope[apiBoundName] = options['gridApi'] = gridApi;
                    if (gridApi.rowEdit) {
                        gridApi.rowEdit.on.saveRow($scope, function (rowEntity) {
                            var defered = $q.defer();
                            $scope[apiBoundName].rowEdit.setSavePromise(rowEntity, defered.promise);
                            defered.resolve();
                            return defered.promise;
                        });
                    }
                    if (gridApi.selection) {
                        gridApi.selection.on.rowSelectionChanged($scope, function (row, event) {
                            if (angular.isFunction(rowSelectionChanged)) {
                                rowSelectionChanged(row, row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows());
                            }
                        });
                        gridApi.selection.on.rowSelectionChangedBatch($scope, function (rows, event) {
                            if (angular.isFunction(rowSelectionChanged)) {
                                angular.forEach(rows, function (row) {
                                    rowSelectionChanged(row, row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows());
                                });
                            }
                        });
                    }
                    gridApi.core.on.sortChanged($scope, function (grid, sortColumns) {
                        var sorts = [];
                        angular.forEach(sortColumns, function (sortColumn, key) {
                            sorts.push({
                                sortBy: sortColumn.colDef.sortBy,
                                direction: sortColumn.sort.direction
                            });
                        });
                        (sortChanged || angular.noop)(sorts);
                    });
                    gridApi.grid.registerDataChangeCallback(function () {
                        if (gridApi.grid.treeBase && (gridApi.grid.treeBase.tree instanceof Array) && tableConfig.expandAll) {
                            gridApi.treeBase.expandAllRows();
                        }
                    });
                    gridApi.grid.registerDataChangeCallback(function (grid) {
                        if (gridApi.grid._selectedRows && gridApi.grid._selectedRows.length > 0) {
                            if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
                                options.defaultSearchCriteria.selectAll = gridApi.grid.selection.selectAll;
                            }
                            angular.forEach(grid.rows, function (row) {
                                if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
                                    gridApi.selection.selectRow(row.entity);
                                } else if (containRow(gridApi.grid, gridApi.grid._selectedRows, row.entity)) {
                                    gridApi.selection.selectRow(row.entity);
                                }
                            });
                        }
                        if (grid.options.selectAll) {
                            angular.forEach(grid.rows, function (row) {
                                gridApi.selection.selectRow(row.entity);
                            });
                        }

                    }, [uiGridConstants.dataChange.ROW]);
                    if (gridApi.colMovable && gridApi.colMovable.raise) {
                        gridApi.colMovable.raise.columnPositionChanged = function (colDef, originalPosition, newPosition) {
                            var order = [];
                            if (gridApi.grid.moveColumns && gridApi.grid.moveColumns.orderCache) {
                                angular.forEach(gridApi.grid.moveColumns.orderCache, function (orderCache) {
                                    order.push(orderCache.colDef.field);
                                });
                            }
                            storageService.saveTableSetting($scope.$state.current.name + ':' + gridApi.grid.options.name, {
                                displayStyle: gridApi.grid.options.displayStyle,
                                order: order
                            });
                        };
                    }
                    $scope.$on('ADD_ROWS', function ($event, rows) {
                        $event.preventDefault();
                        $event.stopPropagation();
                    });
                    $scope.$on('REMOVE_ROWS', function ($event, rows) {
                        $event.preventDefault();
                        $event.stopPropagation();
                    });
                };
                if (tableConfig.hasOwnProperty('enableRowHeaderSelection')) {
                    options.enableRowHeaderSelection = tableConfig.enableRowHeaderSelection;
                }
                options.enableOperation = tableConfig.enableOperation;
                options.enableOperationRemoveSelected = tableConfig.enableOperationRemoveSelected;
                options.addRow = tableConfig.addRow;
                options.removeSelectedRows = tableConfig.removeSelectedRows;
                options.removeAllRows = tableConfig.removeAllRows;
                options.viewRow = tableConfig.viewRow;
                options.editRow = tableConfig.editRow;
                options.addSubRow = tableConfig.addSubRow;
                options.removeRow = tableConfig.removeRow;
                options.data = tableConfig.model;
                options.verifyData = tableConfig.verifyModel;
                options.validatorConfig = tableConfig.validatorConfig;
                options.moreProcess = tableConfig.moreProcess;
                options.moreProcessByEol = tableConfig.moreProcessByEol;
                if (tableConfig.hasOwnProperty('isRowSelectable')) {
                    if (angular.isString(tableConfig.isRowSelectable)) {
                        options.isRowSelectable = $scope.$eval(tableConfig.isRowSelectable);
                    } else if (angular.isFunction(tableConfig.isRowSelectable)) {
                        options.isRowSelectable = tableConfig.isRowSelectable;
                    }
                }
                if (tableConfig.hasOwnProperty('enableGridMenu')) {
                    options.enableGridMenu = tableConfig.enableGridMenu;
                }
                if (tableConfig.hasOwnProperty('multiSelect')) {
                    options.multiSelect = tableConfig.multiSelect;
                }
                if (tableConfig.hasOwnProperty('filterRowOperation')) {
                    options.filterRowOperation = tableConfig.filterRowOperation;
                }
                if (tableConfig.hasOwnProperty('enableVerticalScrollbar')) {
                    options.enableVerticalScrollbar = tableConfig.enableVerticalScrollbar;
                }
                if (tableConfig.hasOwnProperty('enableHorizontalScrollbar')) {
                    options.enableHorizontalScrollbar = tableConfig.enableHorizontalScrollbar;
                }
                if (tableConfig.hasOwnProperty('virtualizationThreshold')) {
                    options.virtualizationThreshold = tableConfig.virtualizationThreshold;
                }
                if (tableConfig.hasOwnProperty('columnVirtualizationThreshold')) {
                    options.columnVirtualizationThreshold = tableConfig.columnVirtualizationThreshold;
                }
                if (tableConfig.hasOwnProperty('minRowsToShow')) {
                    options.minRowsToShow = tableConfig.minRowsToShow;
                }
                if (tableConfig.hasOwnProperty('maxRowsToShow')) {
                    options.maxRowsToShow = tableConfig.maxRowsToShow;
                }
                if (tableConfig.hasOwnProperty('rowHeight')) {
                    options.rowHeight = tableConfig.rowHeight;
                }
                if (tableConfig.hasOwnProperty('enablePagination')) {
                    options.enablePagination = tableConfig.enablePagination;
                }
                if (tableConfig.hasOwnProperty('enableAutoResize')) {
                    options.enableAutoResize = tableConfig.enableAutoResize;
                }
                if (tableConfig.hasOwnProperty('enableColumnResizing')) {
                    options.enableColumnResizing = tableConfig.enableColumnResizing;
                }
                if (tableConfig.hasOwnProperty('enableColumnMoving')) {
                    options.enableColumnMoving = tableConfig.enableColumnMoving;
                }
                if (tableConfig.hasOwnProperty('enableRowSelection')) {
                    options.enableRowSelection = tableConfig.enableRowSelection;
                }
                if (tableConfig.hasOwnProperty('enableRowHeaderSelection')) {
                    options.enableRowHeaderSelection = tableConfig.enableRowHeaderSelection;
                }
                if (tableConfig.hasOwnProperty('enableSorting')) {
                    options.enableSorting = tableConfig.enableSorting;
                }
                if (tableConfig.hasOwnProperty('showColumnFooter')) {
                    options.showColumnFooter = tableConfig.showColumnFooter;
                }
                if (options.addRow) {
                    options.showColumnFooter = true;
                }
                if (tableConfig.hasOwnProperty('selectAll')) {
                    options.selectAll = tableConfig.selectAll;
                }
                if (tableConfig.hasOwnProperty('id')) {
                    options.id = tableConfig.id;
                }
                if (tableConfig.hasOwnProperty('showHeader')) {
                    options.showHeader = tableConfig.showHeader;
                }
                if (tableConfig.hasOwnProperty('noUnselect')) {
                    options.noUnselect = tableConfig.noUnselect;
                }
                return options;
            }

            function createGridOptions($scope, tableConfig, paginationChanged, rowSelectionChanged, sortChanged, apiBoundName, columnActive) {
                var defaultSort, defaultSearchCriteria, options, watcher;
                var tableSetting = storageService.getTableSetting($scope.$state.current.name + ':' + tableConfig.name);
                apiBoundName = apiBoundName || tableConfig.apiBoundName || 'gridApi';
                // set default value
                if (tableConfig.storageSearchCriteria == undefined)
                    tableConfig.storageSearchCriteria = true;
                if (tableConfig.storageSearchCriteria)
                    defaultSearchCriteria = storageService.getSearchCriteria($scope.$state.current.name);
                defaultSearchCriteria = defaultSearchCriteria || {
                    storageSearchCriteria: tableConfig.storageSearchCriteria,
                    $type: 'SearchCriteria',
                    $state: $scope.$state.current.name,
                    pageNo: provider.defaultGridOptions.paginationCurrentPage,
                    pageSize: provider.defaultGridOptions.paginationPageSize,
                    list: []
                };
                defaultSearchCriteria.pageNum = defaultSearchCriteria.pageNum || provider.defaultGridOptions.paginationCurrentPage;
                defaultSearchCriteria.totalPages = 0;
                options = angular.copy(provider.defaultGridOptions);
                // i18nService.setCurrentLang($rootScope.I18N.language);
                i18nService.setCurrentLang('en');
                // options.gridMenuTitleFilter = $translate;
                options.defaultSearchCriteria = defaultSearchCriteria;
                options.name = tableConfig.name;
                defaultSort = prepareColumnDefs($scope, tableConfig, options, tableSetting);
                options.paginationPageSize = defaultSearchCriteria.pageSize || options.paginationPageSize;
                options.defaultSearchCriteria.sortBy = defaultSearchCriteria.sortBy || defaultSort.sortBy;
                options.defaultSearchCriteria.sortDirection = defaultSearchCriteria.sortDirection || defaultSort.sortDirection;
                options.columnDefs = tableConfig.columnDefs || [];
				/*if (options.enableVerticalScrollbar == uiGridConstants.scrollbars.NEVER && options.columnDefs.length > 0) {
					options.columnDefs[options.columnDefs.length - 1].pinnedRight = true;
				}*/
                options.columnActive = function (content) {
                    if (angular.isFunction(columnActive)) {
                        columnActive();
                    }
                };
                options.onRegisterApi = function (gridApi) {
                    $scope[apiBoundName] = options['gridApi'] = gridApi;
                    gridApi.setSelectedRows = function (rows) {
                        gridApi.grid._selectedRows = rows;
                    };
                    if (gridApi.rowEdit) {
                        gridApi.rowEdit.on.saveRow($scope, function (rowEntity) {
                            var defered = $q.defer();
                            $scope[apiBoundName].rowEdit.setSavePromise(rowEntity, defered.promise);
                            defered.resolve();
                            return defered.promise;
                        });
                    }
                    if (gridApi.pagination) {
                        gridApi.pagination.on.paginationChanged($scope, function (pageNum, pageSize) {
                            if (options.defaultSearchCriteria.pageNum != pageNum) {
                                gridApi.grid.selection.selectAll = false;
                            }
                            if (angular.isFunction(paginationChanged)) {
                                paginationChanged(pageNum, pageSize);
                            }
                        });
                    }
                    if (gridApi.selection) {

                        gridApi.selection.on.rowSelectionChanged($scope, function (row, event) {
                            var rows;
                            if (row.grid._selectedRows) {
                                if (row.isSelected) {
                                    addRow(row.grid, row.grid._selectedRows, row.entity);
                                    if (GridConstants.MULTI_PAGE_SELECT_MAX < row.grid._selectedRows.length) {
                                        modalService.openErrorDialogs({
                                            'messages': ['error.grid.maxselected']
                                        });
                                        gridApi.selection.unSelectRow(row.entity);
                                        return;
                                    }
                                } else {
                                    removeRow(row.grid, row.grid._selectedRows, row.entity);
                                }
                            }
                            if (angular.isFunction(rowSelectionChanged)) {
                                rowSelectionChanged(row, row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows());
                            }
                            rows = row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows();
                            if (rows.length == 1) {
                                var dataType = rows[0].currentDataType || rows[0].wfTasktype;
                                var dataKey = rows[0].primaryKey || rows[0].wfItemKey;
                                var dataStatus = rows[0].wfStatusCode || rows[0].taskDisplayName;
                                var serviceCode = rows[0].serviceCode || $rootScope.serviceCode;
                                // only main grid table need call the method.
                                if (dataType && dataKey) {
                                    if ($scope.$resolve && $scope.$resolve.dialogsModule) {
                                        if ($scope.$resolve.dialogsModule.enableViewAuditOrNote) {
                                            $rootScope.initAuditOrNoteParams(dataType, dataKey, dataStatus, serviceCode, rows[0].taskId);
                                        }
                                    } else {
                                        $rootScope.initAuditOrNoteParams(dataType, dataKey, dataStatus, serviceCode, rows[0].taskId);
                                    }
                                }
                            } else {
                                $rootScope.removeAuditOrNoteParams();
                            }
                        });
                        // fixed bug for multi selected
                        gridApi.selection.on.rowSelectionChangedBatch($scope, function (rows, event) {
                            var i = 0;
                            if (rows.length > 0 && rows[0].grid._selectedRows) {
                                for (i = 0; i < rows.length; i++) {
                                    if (rows[i].isSelected) {
                                        addRow(rows[i].grid, rows[i].grid._selectedRows, rows[i].entity);
                                        if (GridConstants.MULTI_PAGE_SELECT_MAX < rows[i].grid._selectedRows.length) {
                                            modalService.openErrorDialogs({
                                                'messages': ['error.grid.maxselected']
                                            });
                                            break;
                                        }
                                    } else {
                                        removeRow(rows[i].grid, rows[i].grid._selectedRows, rows[i].entity);
                                    }
                                }
                                for (; i < rows.length; i++) {
                                    if (rows[i].isSelected) {
                                        gridApi.selection.unSelectRow(rows[i].entity);
                                    }
                                }
                            }
                            if (angular.isFunction(rowSelectionChanged)) {
                                angular.forEach(rows, function (row) {
                                    rowSelectionChanged(row, row.grid._selectedRows ? row.grid._selectedRows : gridApi.selection.getSelectedRows());
                                });
                            }
                        });
                    }
                    gridApi.core.on.sortChanged($scope, function (grid, sortColumns) {
                        var sorts = [];
                        angular.forEach(sortColumns, function (sortColumn, key) {
                            sorts.push({
                                sortBy: sortColumn.colDef.sortBy,
                                direction: sortColumn.sort.direction
                            });
                        });
                        (sortChanged || angular.noop)(sorts);
                    });
                    gridApi.grid.registerDataChangeCallback(function () {
                        if (gridApi.grid.treeBase) {
                            if (gridApi.grid.treeBase.tree instanceof Array && tableConfig.expandAll) {
                                gridApi.treeBase.expandAllRows();
                            }
                        }
                    });
                    gridApi.grid.registerDataChangeCallback(function (grid) {
                        if (gridApi.grid._selectedRows && gridApi.grid._selectedRows.length > 0) {
                            if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
                                options.defaultSearchCriteria.selectAll = gridApi.grid.selection.selectAll;
                            }
                            angular.forEach(grid.rows, function (row) {
                                if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
                                    gridApi.selection.selectRow(row.entity);
                                } else if (containRow(gridApi.grid, gridApi.grid._selectedRows, row.entity)) {
                                    gridApi.selection.selectRow(row.entity);
                                }
                            });
                        }
                        if (grid.options.selectAll) {
                            angular.forEach(grid.rows, function (row) {
                                gridApi.selection.selectRow(row.entity);
                            });
                        }
                    }, [uiGridConstants.dataChange.ROW]);
                    watcher = $scope.$watch(function () {
                        return options.multiSelect && options.multiPageSelect;
                    }, function (multiPageSelect) {
                        if (multiPageSelect === true) {
                            gridApi.grid._selectedRows = gridApi.grid._selectedRows || [];
                        } else {
                            delete gridApi.grid._selectedRows;
                        }
                    });
                    if (gridApi.colMovable && gridApi.colMovable.raise) {
                        gridApi.colMovable.raise.columnPositionChanged = function (colDef, originalPosition, newPosition) {
                            var order = [];
                            if (gridApi.grid.moveColumns && gridApi.grid.moveColumns.orderCache) {
                                angular.forEach(gridApi.grid.moveColumns.orderCache, function (orderCache) {
                                    order.push(orderCache.colDef.field);
                                });
                            }
                            storageService.saveTableSetting($scope.$state.current.name + ':' + gridApi.grid.options.name, {
                                displayStyle: gridApi.grid.options.displayStyle,
                                order: order
                            });
                        };
                    }
                    $scope.$on('$destroy', function () {
                        watcher();
                    });
                    $scope.$on('ADD_ROWS', function ($event, rows) {
                        $event.preventDefault();
                        $event.stopPropagation();
                    });
                    $scope.$on('REMOVE_ROWS', function ($event, rows) {
                        if (gridApi.grid._selectedRows) {
                            if (gridApi.grid.selection.selectAll && supportMultiPageSelectAll) {
                                gridApi.grid._selectedRows.splice(0, gridApi.grid._selectedRows.length);
                            } else {
                                angular.forEach(gridApi.grid._selectedRows, function (rowEntity) {
                                    removeRow(gridApi.grid, gridApi.grid._selectedRows, rowEntity);
                                });
                            }
                        }
                        $event.preventDefault();
                        $event.stopPropagation();
                    });
                };
                if (tableConfig.hasOwnProperty('enableRowHeaderSelection')) {
                    options.enableRowHeaderSelection = tableConfig.enableRowHeaderSelection;
                }
                options.enableOperation = tableConfig.enableOperation;
                options.enableOperationRemoveSelected = tableConfig.enableOperationRemoveSelected;
                options.addRow = tableConfig.addRow;
                options.removeSelectedRows = tableConfig.removeSelectedRows;
                options.removeAllRows = tableConfig.removeAllRows;
                options.viewRow = tableConfig.viewRow;
                options.editRow = tableConfig.editRow;
                options.addSubRow = tableConfig.addSubRow;
                options.removeRow = tableConfig.removeRow;
                options.data = tableConfig.model;
                options.verifyData = tableConfig.verifyModel;
                options.validatorConfig = tableConfig.validatorConfig;
                options.moreProcess = tableConfig.moreProcess;
                options.moreProcessByEol = tableConfig.moreProcessByEol;
                if (tableConfig.hasOwnProperty('isRowSelectable')) {
                    if (angular.isString(tableConfig.isRowSelectable)) {
                        options.isRowSelectable = $scope.$eval(tableConfig.isRowSelectable);
                    } else if (angular.isFunction(tableConfig.isRowSelectable)) {
                        options.isRowSelectable = tableConfig.isRowSelectable;
                    }
                }
                if (tableConfig.hasOwnProperty('enableGridMenu')) {
                    options.enableGridMenu = tableConfig.enableGridMenu;
                }
                if (tableConfig.hasOwnProperty('multiSelect')) {
                    options.multiSelect = tableConfig.multiSelect;
                }
                if (tableConfig.hasOwnProperty('multiPageSelect')) {
                    options.multiPageSelect = tableConfig.multiPageSelect;
                }
                if (tableConfig.hasOwnProperty('filterRowOperation')) {
                    options.filterRowOperation = tableConfig.filterRowOperation;
                }
                if (tableConfig.hasOwnProperty('enablePaginationControls')) {
                    options.enablePaginationControls = tableConfig.enablePaginationControls;
                }
                if (tableConfig.hasOwnProperty('enableVerticalScrollbar')) {
                    options.enableVerticalScrollbar = tableConfig.enableVerticalScrollbar;
                }
                if (tableConfig.hasOwnProperty('enableHorizontalScrollbar')) {
                    options.enableHorizontalScrollbar = tableConfig.enableHorizontalScrollbar;
                }
                if (tableConfig.hasOwnProperty('virtualizationThreshold')) {
                    options.virtualizationThreshold = tableConfig.virtualizationThreshold;
                }
                if (tableConfig.hasOwnProperty('columnVirtualizationThreshold')) {
                    options.columnVirtualizationThreshold = tableConfig.columnVirtualizationThreshold;
                }
                if (tableConfig.hasOwnProperty('minRowsToShow')) {
                    options.minRowsToShow = tableConfig.minRowsToShow;
                }
                if (tableConfig.hasOwnProperty('maxRowsToShow')) {
                    options.maxRowsToShow = tableConfig.maxRowsToShow;
                }
                if (tableConfig.hasOwnProperty('rowHeight')) {
                    options.rowHeight = tableConfig.rowHeight;
                }
                if (tableConfig.hasOwnProperty('enablePagination')) {
                    options.enablePagination = tableConfig.enablePagination;
                }
                if (tableConfig.hasOwnProperty('enableAutoResize')) {
                    options.enableAutoResize = tableConfig.enableAutoResize;
                }
                if (tableConfig.hasOwnProperty('enableColumnResizing')) {
                    options.enableColumnResizing = tableConfig.enableColumnResizing;
                }
                if (tableConfig.hasOwnProperty('enableColumnMoving')) {
                    options.enableColumnMoving = tableConfig.enableColumnMoving;
                }
                if (tableConfig.hasOwnProperty('enableRowSelection')) {
                    options.enableRowSelection = tableConfig.enableRowSelection;
                }
                if (tableConfig.hasOwnProperty('enableRowHeaderSelection')) {
                    options.enableRowHeaderSelection = tableConfig.enableRowHeaderSelection;
                }
                if (tableConfig.hasOwnProperty('enableSorting')) {
                    options.enableSorting = tableConfig.enableSorting;
                }
                if (tableConfig.hasOwnProperty('selectAll')) {
                    options.selectAll = tableConfig.selectAll;
                }
                if (tableConfig.hasOwnProperty('showColumnFooter')) {
                    options.showColumnFooter = tableConfig.showColumnFooter;
                }
                if (options.addRow) {
                    options.showColumnFooter = true;
                }
                if (tableConfig.hasOwnProperty('id')) {
                    options.id = tableConfig.id;
                }
                if (tableConfig.hasOwnProperty('showHeader')) {
                    options.showHeader = tableConfig.showHeader;
                }
                if (tableConfig.hasOwnProperty('noUnselect')) {
                    options.noUnselect = tableConfig.noUnselect;
                }
                return options;
            }

            function prepareColumnDefs($scope, tableConfig, options, tableSetting) {
                var newColDefs = [], defaultSort = {}, i, watcher;
                options.appScopeProvider = options.appScope = $scope;
                angular.forEach(tableConfig.columnDefs, function (column, key) {
                    // set validatorConfig.
                    column.validatorConfig = tableConfig.validatorConfig;
                    column.sortDirectionCycle = [uiGridConstants.ASC, uiGridConstants.DESC];
                    if (column.sort) {
                        defaultSort.sortBy = column.sortBy;
                        defaultSort.sortDirection = column.sort.direction;
                    } else {
                        column.sort = {};
                    }
                    if (column.type && options.type != 'label' && options.type != 'image') {
                        column.cellTemplate = column.template || column.cellTemplate || provider.fsGridTemplate;
                    } else if (column.template) {
                        column.cellTemplate = column.template;
                    }
                    column.displayName = column.displayName || column.label;
                    delete column.label;
                    column.field = column.field || column.model;
                    column.cellFilter = column.cellFilter || column.filter;
					/*
					 * column.cellTooltip = function() { return $scope.fsGridConfig.tooltipMessage; };
					 */
                    if (column.displayName) {
                        $translate(column.displayName).then(function (displayName) {
                            column.displayName = displayName;
                        }, angular.noop);
                    }
                    if (angular.isString(column.options)) {
                        watcher = $scope.$watch(column.options, function (newValue, oldValue) {
                            column.options = newValue;
                        });
                        $scope.$on('$destroy', function () {
                            watcher();
                        });
                    } else {
                        column.options = column.options;
                    }
                    if (tableSetting && tableSetting.displayStyle) {
                        options.displayStyle = tableSetting.displayStyle;
                    } else if (!options.displayStyle) {
                        if (angular.isNumber(column.width) || (angular.isString(column.width) && column.width.match(/^(\d+)[%]$/))) {
                            options.displayStyle = 'normal';
                        } else if (angular.isNumber(column.minWidth) || (angular.isString(column.minWidth) && column.minWidth.match(/^(\d+)$/))) {
                            options.displayStyle = 'normal';
                        } else {
                            options.displayStyle = 'all';
                        }
                    }
                    if (tableSetting && tableSetting.visible) {
                        column.visible = tableSetting.visible[column.field];
                    }
                    if (tableSetting && tableSetting.width && tableSetting.width['_' + options.displayStyle] && tableSetting.width['_' + options.displayStyle][column.field]) {
                        column.width = tableSetting.width['_' + options.displayStyle][column.field].adjustWidth;
                    }
                });
                if (tableSetting && tableSetting.order) {
                    angular.forEach(tableSetting.order, function (columnField) {
                        for (i = 0; i < tableConfig.columnDefs.length; i++) {
                            if (columnField == tableConfig.columnDefs[i].field) {
                                newColDefs.push(tableConfig.columnDefs[i]);
                                break;
                            }
                        }
                    });
                    tableConfig.columnDefs = newColDefs;
                }
                return defaultSort;
            }

            function updateGridOptions(searchCriteria, gridOptions) {
                var columnDefs = gridOptions.columnDefs;
                var i, columns = gridOptions.gridApi ? gridOptions.gridApi.grid.renderContainers.body.renderedColumns : undefined;
                gridOptions.totalItems = searchCriteria.total;
                if (searchCriteria.sortBy && searchCriteria.sortDirection) {
                    angular.forEach(columnDefs, function (column, key) {
                        if (column.sortBy == searchCriteria.sortBy) {
                            column.sort = column.sort || {};
                            column.sort.direction = searchCriteria.sortDirection;
                            for (i = 0; columns && i < columns.length; i++) {
                                if (columns[i].field == column.field) {
                                    columns[i].sort = columns[i].sort || {};
                                    columns[i].sort.direction = searchCriteria.sortDirection;
                                    break;
                                }
                            }
                        } else if (column.sort) {
                            delete column.sort.direction;
                            for (i = 0; columns && i < columns.length; i++) {
                                if (columns[i].field == column.field) {
                                    delete columns[i].sort.direction;
                                    break;
                                }
                            }
                        }
                    });
                }
                if (searchCriteria.pageNum) {
                    gridOptions.paginationCurrentPage = searchCriteria.pageNum;
                }
                if (searchCriteria.pageSize) {
                    gridOptions.paginationPageSize = searchCriteria.pageSize;
                }
            }

            function containRow(grid, dstRows, rowEntity) {
                var i = 0;
                for (i = 0; i < dstRows.length; i++) {
                    if (grid.options.rowEquality(dstRows[i], rowEntity) || (dstRows[i].primaryKey == rowEntity.primaryKey && rowEntity.primaryKey != undefined)) {
                        dstRows[i] = rowEntity;
                        return true;
                    }
                }
                return false;
            }

            function addRow(grid, dstRows, rowEntity) {
                var i = 0;
                if (grid.selection.selectAll && supportMultiPageSelectAll) {
                    return;
                }
                if (dstRows.length == 0) {
                    dstRows.push(rowEntity);
                    return;
                }
                for (i = 0; i < dstRows.length; i++) {
                    if (grid.options.rowEquality(dstRows[i], rowEntity) || (dstRows[i].primaryKey == rowEntity.primaryKey && rowEntity.primaryKey != undefined)) {
                        break;
                    }
                }
                if (i >= dstRows.length) {
                    dstRows.push(rowEntity);
                }
            }

            function removeRow(grid, dstRows, rowEntity) {
                var i = 0;
                if (grid.selection.selectAll && supportMultiPageSelectAll) {
                    dstRows.splice(0, dstRows.length);
                    return;
                }
                for (i = 0; i < dstRows.length; i++) {
                    if (grid.options.rowEquality(dstRows[i], rowEntity) || (dstRows[i].primaryKey == rowEntity.primaryKey && rowEntity.primaryKey != undefined)) {
                        dstRows.splice(i, 1);
                        return;
                    }
                }
            }

            return {
                createGridOptions: createGridOptions,
                createInnerGridOptions: createInnerGridOptions,
                updateGridOptions: updateGridOptions,
                removeSelectedRows: removeSelectedRows,
                removeRows: removeRows
            };
        }
    }

    uiGridCustomerScrollbar.$inject = ['$timeout', '$parse', '$window', 'gridUtil', 'ScrollEvent'];
    function uiGridCustomerScrollbar($timeout, $parse, $window, gridUtil, ScrollEvent) {
        var uiGridCustomerScrollbarOptions = ['handlers', 'wheelSpeed', 'wheelPropagation', 'swipeEasing', 'minScrollbarLength', 'maxScrollbarLength', 'scrollingThreshold', 'useBothWheelAxes', 'suppressScrollX',
            'suppressScrollY', 'scrollXMarginOffset', 'scrollYMarginOffset',];
        return {
            priority: -200,
            transclude: true,
            replace: true,
            require: ['^uiGrid', '^uiGridRenderContainer'],
            template: '<div ng-transclude class="open" ng-click="clickEvent($event)"></div>',
            link: {
                pre: function ($scope, $elem, $attrs, controllers) {
                    var jqWindow = angular.element($window);
                    var options = {};
                    var perfect;
                    var uiGridCtrl = controllers[0];
                    var grid = uiGridCtrl.grid;
                    var containerCtrl = controllers[1];
                    var rowContainer = containerCtrl.rowContainer;
                    var colContainer = containerCtrl.colContainer;
                    grid._scrollBars = grid._scrollBars || [];
                    $scope.scrollHandler = function (position) {
                        var newScrollTop = position.scrollTop;
                        var newScrollLeft = position.scrollLeft;//gridUtil.normalizeScrollLeft($elem, grid);

                        var vertScrollPercentage = rowContainer.scrollVertical(newScrollTop);
                        var horizScrollPercentage = colContainer.scrollHorizontal(newScrollLeft);

                        var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);
                        scrollEvent.newScrollLeft = newScrollLeft;
                        scrollEvent.newScrollTop = newScrollTop;
                        if (horizScrollPercentage > -1) {
                            scrollEvent.x = { percentage: horizScrollPercentage };
                        }

                        if (vertScrollPercentage > -1) {
                            scrollEvent.y = { percentage: vertScrollPercentage };
                        }

                        grid.scrollContainers($scope.$parent.containerId, scrollEvent);
                        angular.forEach(grid._scrollBars, function (scrollbar) {
                            if (perfect != scrollbar) {
                                scrollbar.lastScrollTop = perfect.lastScrollTop;
                                scrollbar.element.scrollLeft = perfect.element.scrollLeft;

                                scrollbar.lastScrollLeft = perfect.lastScrollLeft;
                                scrollbar.element.scrollTop = perfect.element.scrollTop;

                                scrollbar.onScroll();
                            }
                        });
                    }

                    for (var i = 0, l = uiGridCustomerScrollbarOptions.length; i < l; i++) {
                        var opt = uiGridCustomerScrollbarOptions[i];

                        if ($attrs[opt] !== undefined) {
                            options[opt] = $parse($attrs[opt])();
                        }
                    }

                    if (grid.options.enableHorizontalScrollbar == 0) {
                        options['suppressScrollX'] = true;
                    }
                    if (grid.options.enableVerticalScrollbar == 0) {
                        options['suppressScrollY'] = true;
                    }

                    $scope.clickEvent = function ($event) {
                        var element = $event.srcElement || $event.target;
                        element = angular.element(element);
                        if (element && (element.hasClass('ps__rail-x') || element.hasClass('ps__rail-y') || element.hasClass('ps__thumb-x') || element.hasClass('ps__thumb-y'))) {
                            $event.stopPropagation();
                        }
                    };
                    $scope.$evalAsync(function () {
                        perfect = new PerfectScrollbar($elem[0], options);
                        grid._scrollBars.push(perfect);
                        var onScrollHandler = $parse($attrs.onScroll)($scope);
                        var onScrollYEndHandler = $parse($attrs.onScrollYEnd)($scope);
                        if (onScrollYEndHandler) {
                            $elem.on('ps-y-reach-end', function () {
                                var scrollTop = $elem.prop('scrollTop');
                                var scrollHeight = $elem.prop('scrollHeight') - $elem[0].clientHeight;
                                var scrollLeft = $elem.prop('scrollLeft');
                                var scrollWidth = $elem.prop('scrollWidth') - $elem[0].clientWidth;

                                onScrollYEndHandler({
                                    scrollTop: scrollTop,
                                    scrollHeight: scrollHeight,
                                    scrollLeft: scrollLeft,
                                    scrollWidth: scrollWidth
                                });
                            });
                        }
                        if (onScrollHandler) {
                            var mouseWheeltoBind = ('onwheel' in document || document.documentMode >= 9) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
                            var renderContainer = angular.element($elem[0].parentElement.parentElement);
                            angular.forEach(mouseWheeltoBind, function (bind) {
                                var cbs = renderContainer.data('mousewheel-callbacks');
                                angular.forEach(cbs, function (fn) {
                                    renderContainer.off(mouseWheeltoBind[--i], fn);
                                });
                            });
                            $elem.on('scroll', function () {
                                var scrollTop = $elem.prop('scrollTop');
                                var scrollHeight = $elem.prop('scrollHeight') - $elem[0].clientHeight;
                                var scrollLeft = $elem.prop('scrollLeft');
                                var scrollWidth = $elem.prop('scrollWidth') - $elem[0].clientWidth;

                                $scope.$apply(function () {
                                    onScrollHandler({
                                        scrollTop: scrollTop,
                                        scrollHeight: scrollHeight,
                                        scrollLeft: scrollLeft,
                                        scrollWidth: scrollWidth
                                    });
                                });
                            });
                        }
                    });

                    // Automatically update when content height changes
                    $scope.$watch(function () {
                        return $elem.prop('scrollHeight');
                    }, function (newValue, oldValue) {
                        if (newValue) {
                            update('contentSizeChange');
                        }
                    });
                    $scope.$on('scrollbar-resize', function ($event) {
                        if (perfect) {
                            perfect.update('mouseenter');
                        }
                        if ($event.preventDefault) {
                            $event.preventDefault();
                        }
                        if ($event.stopPropagation) {
                            $event.stopPropagation();
                        }
                    });
                    function update(event) {
                        $scope.$evalAsync(function () {
                            if ($attrs.scrollDown == 'true' && event != 'mouseenter') {
                                setTimeout(function () {
                                    $elem[0].scrollTop = $elem.prop("scrollHeight");
                                }, 100);
                            }
                            if (perfect) {
                                perfect.update();
                            }
                        });
                    }

                    // This is necessary when you don't watch anything with the scrollbar
                    $elem.on('mouseenter', function () {
                        update('mouseenter');
                    });

                    // Possible future improvement: check the type here and use the appropriate watch for non-arrays
                    if ($attrs.refreshOnChange) {
                        $scope.$watchCollection($attrs.refreshOnChange, function () {
                            update();
                        });
                    }

                    // Rebuild on window resize
                    if ($attrs.refreshOnResize) {
                        jqWindow.on('resize', function () {
                            update();
                        });
                    }

                    if ($attrs.updateOn) {
                        $attrs.updateOn.split(' ').forEach(function (eventName) {
                            $scope.$on(eventName, update);
                        });
                    }

                    // Unbind resize event and destroy instance
                    $elem.on('$destroy', function () {
                        $elem.off();
                        jqWindow.off('resize', function () {
                            update();
                        });
                        if (perfect) {
                            perfect.destroy();
                            perfect = null;
                        }
                    });
                }
            }
        };
    }

    uiGridCustomerColumnResizer.$inject = ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', '$injector'];
    function uiGridCustomerColumnResizer($document, gridUtil, uiGridConstants, uiGridResizeColumnsService, $injector) {//change db click logic
        var resizeOverlay = angular.element('<div class="ui-grid-resize-overlay"></div>');

        var resizer = {
            priority: 0,
            scope: {
                col: '=',
                position: '@',
                renderIndex: '='
            },
            require: '?^uiGrid',
            link: function ($scope, $elm, $attrs, uiGridCtrl) {
                var startX = 0,
                    x = 0,
                    gridLeft = 0,
                    rtlMultiplier = 1;

                //when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
                if (uiGridCtrl.grid.isRTL()) {
                    $scope.position = 'left';
                    rtlMultiplier = -1;
                }

                if ($scope.position === 'left') {
                    $elm.addClass('left');
                }
                else if ($scope.position === 'right') {
                    $elm.addClass('right');
                }

                // Refresh the grid canvas
                //   takes an argument representing the diff along the X-axis that the resize had
                function refreshCanvas(xDiff) {
                    // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size
                    uiGridCtrl.grid.refreshCanvas(true).then(function () {
                        uiGridCtrl.grid.queueGridRefresh();
                    });
                }

                // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth
                // Returns the new recommended with, after constraints applied
                function constrainWidth(col, width) {
                    var newWidth = width;

                    // If the new width would be less than the column's allowably minimum width, don't allow it
                    if (col.minWidth && newWidth < col.minWidth) {
                        newWidth = col.minWidth;
                    }
                    else if (col.maxWidth && newWidth > col.maxWidth) {
                        newWidth = col.maxWidth;
                    }

                    return newWidth;
                }


				/*
				 * Our approach to event handling aims to deal with both touch devices and mouse devices
				 * We register down handlers on both touch and mouse.  When a touchstart or mousedown event
				 * occurs, we register the corresponding touchmove/touchend, or mousemove/mouseend events.
				 *
				 * This way we can listen for both without worrying about the fact many touch devices also emulate
				 * mouse events - basically whichever one we hear first is what we'll go with.
				 */
                function moveFunction(event, args) {
                    if (event.originalEvent) { event = event.originalEvent; }
                    event.preventDefault();

                    x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;

                    if (x < 0) { x = 0; }
                    else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }

                    var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);

                    // Don't resize if it's disabled on this column
                    if (col.colDef.enableColumnResizing === false) {
                        return;
                    }

                    if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {
                        uiGridCtrl.grid.element.addClass('column-resizing');
                    }

                    // Get the diff along the X axis
                    var xDiff = x - startX;

                    // Get the width that this mouse would give the column
                    var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);

                    // check we're not outside the allowable bounds for this column
                    x = x + (constrainWidth(col, newWidth) - newWidth) * rtlMultiplier;

                    resizeOverlay.css({ left: x + 'px' });

                    uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);
                }


                function upFunction(event, args) {
                    if (event.originalEvent) { event = event.originalEvent; }
                    event.preventDefault();

                    uiGridCtrl.grid.element.removeClass('column-resizing');

                    resizeOverlay.remove();

                    // Resize the column
                    x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;
                    var xDiff = x - startX;

                    if (xDiff === 0) {
                        // no movement, so just reset event handlers, including turning back on both
                        // down events - we turned one off when this event started
                        offAllEvents();
                        onDownEvents();
                        return;
                    }

                    var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);

                    // Don't resize if it's disabled on this column
                    if (col.colDef.enableColumnResizing === false) {
                        return;
                    }

                    // Get the new width
                    var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);

                    // check we're not outside the allowable bounds for this column
                    col.width = constrainWidth(col, newWidth);
                    col.hasCustomWidth = true;

                    refreshCanvas(xDiff);

                    uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);

                    // stop listening of up and move events - wait for next down
                    // reset the down events - we will have turned one off when this event started
                    offAllEvents();
                    onDownEvents();
                }


                var downFunction = function (event, args) {
                    if (event.originalEvent) { event = event.originalEvent; }
                    event.stopPropagation();

                    // Get the left offset of the grid
                    // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;
                    gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;

                    // Get the starting X position, which is the X coordinate of the click minus the grid's offset
                    startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;

                    // Append the resizer overlay
                    uiGridCtrl.grid.element.append(resizeOverlay);

                    // Place the resizer overlay at the start position
                    resizeOverlay.css({ left: startX });

                    // Add handlers for move and up events - if we were mousedown then we listen for mousemove and mouseup, if
                    // we were touchdown then we listen for touchmove and touchup.  Also remove the handler for the equivalent
                    // down event - so if we're touchdown, then remove the mousedown handler until this event is over, if we're
                    // mousedown then remove the touchdown handler until this event is over, this avoids processing duplicate events
                    if (event.type === 'touchstart') {
                        $document.on('touchend', upFunction);
                        $document.on('touchmove', moveFunction);
                        $elm.off('mousedown', downFunction);
                    } else {
                        $document.on('mouseup', upFunction);
                        $document.on('mousemove', moveFunction);
                        $elm.off('touchstart', downFunction);
                    }
                };

                var onDownEvents = function () {
                    $elm.on('mousedown', downFunction);
                    $elm.on('touchstart', downFunction);
                };

                var offAllEvents = function () {
                    $document.off('mouseup', upFunction);
                    $document.off('touchend', upFunction);
                    $document.off('mousemove', moveFunction);
                    $document.off('touchmove', moveFunction);
                    $elm.off('mousedown', downFunction);
                    $elm.off('touchstart', downFunction);
                };

                onDownEvents();


                // On doubleclick, resize to fit all rendered cells
                var dblClickFn = function (event, args) {
                    event.stopPropagation();

                    var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);

                    // Don't resize if it's disabled on this column
                    if (col.colDef.enableColumnResizing === false) {
                        return;
                    }
                    var storageService = $injector.get('storageService');
                    var setting = storageService.getTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_')) || {};
                    var newWidth = setting.width && setting.width[col.field] ? setting.width[col.field].width : col.drawnWidth;
                    xDiff = newWidth - col.drawnWidth;
                    col.width = newWidth;
                    col.hasCustomWidth = true;

                    refreshCanvas(xDiff);

                    uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);
                };
                $elm.on('dblclick', dblClickFn);

                $elm.on('$destroy', function () {
                    $elm.off('dblclick', dblClickFn);
                    offAllEvents();
                });
            }
        };

        return resizer;
    }

    uiGridMenuCustomerButton.$inject = ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', 'i18nService', '$timeout', '$injector', 'GridConstants'];
    function uiGridMenuCustomerButton(gridUtil, uiGridConstants, uiGridGridMenuService, i18nService, $timeout, $injector, GridConstants) {//add show all and normal
        return {
            priority: 0,
            scope: true,
            require: ['^uiGrid'],
            templateUrl: 'ui-grid/ui-grid-menu-button',
            replace: true,

            link: function ($scope, $elm, $attrs, controllers) {
                var uiGridCtrl = controllers[0], storageService = $injector.get('storageService');

                // For the aria label
                $scope.i18n = {
                    aria: i18nService.getSafeText('gridMenu.aria')
                };

                uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);
                uiGridCtrl.grid.options.displayStyle = uiGridCtrl.grid.options.displayStyle || 'normal';
                if (uiGridCtrl.grid.api.colResizable) {
                    uiGridCtrl.grid.api.colResizable.on.columnSizeChanged($scope, function (colDef, deltaChange) {
                        if (storageService) {
                            var setting = storageService.getTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_')) || {};
                            var column;
                            for (i = 0; i < uiGridCtrl.grid.columns.length; i++) {
                                if (uiGridCtrl.grid.columns[i].field == colDef.field) {
                                    column = uiGridCtrl.grid.columns[i];
                                    break;
                                }
                            }
                            setting.width = setting.width || {};
                            if (!setting.width[colDef.field]) {
                                setting.width[colDef.field] = {
                                    width: colDef.width,
                                    minWidth: colDef.minWidth
                                };
                            }
                            setting.width['_' + uiGridCtrl.grid.options.displayStyle] = setting.width['_' + uiGridCtrl.grid.options.displayStyle] || {};
                            setting.width['_' + uiGridCtrl.grid.options.displayStyle][colDef.field] = setting.width['_' + uiGridCtrl.grid.options.displayStyle][colDef.field] || {};
                            setting.width['_' + uiGridCtrl.grid.options.displayStyle][colDef.field].adjustWidth = column.width;
                            setting.displayStyle = uiGridCtrl.grid.options.displayStyle;
                            storageService.saveTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_'), setting);
                        }
                    });
                }
                if (uiGridCtrl.grid.api.colMovable && uiGridCtrl.grid.api.colMovable.raise) {
                    uiGridCtrl.grid.api.colMovable.raise.columnPositionChanged = function (colDef, originalPosition, newPosition) {
                        if (storageService) {
                            var order = [];
                            if (uiGridCtrl.grid.api.grid.moveColumns && uiGridCtrl.grid.api.grid.moveColumns.orderCache) {
                                angular.forEach(uiGridCtrl.grid.api.grid.moveColumns.orderCache, function (orderCache) {
                                    order.push(orderCache.colDef.field);
                                });
                            }
                            storageService.saveTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_'), {
                                displayStyle: uiGridCtrl.grid.api.grid.options.displayStyle,
                                order: order
                            });
                            if (uiGridCtrl.grid.options.displayStyle == 'all') {
                                $scope.showAll();
                            } else {
                                $scope.showNormal();
                            }
                        }
                    };
                }
                $scope.$on(GridConstants.NOTIFY_HIDE_COLUMN, function (event, args) {
                    if (uiGridCtrl.grid.options.displayStyle == 'all') {
                        $scope.showAll();
                    } else {
                        $scope.showNormal();
                    }
                });
                $scope.shown = false;
                $scope.toggleDisplayStyle = function () {
                    if ($scope.switchChecked) {
                        uiGridCtrl.grid.options.displayStyle = 'all';
                        $scope.showAll();
                    } else {
                        uiGridCtrl.grid.options.displayStyle = 'normal'
                        $scope.showNormal();
                    }
                    storageService.saveTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_'), {
                        displayStyle: uiGridCtrl.grid.options.displayStyle
                    });
                };
                $scope.showAll = function () {
                    var tableSetting, needSaveSetting;
                    tableSetting = storageService.getTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_'));
                    angular.forEach(uiGridCtrl.grid.columns, function (column, index) {
                        var originalSetting;
                        if (column.field && column.field.indexOf('RowHeaderCol') < 0) {
                            if (tableSetting && tableSetting.width && tableSetting.width[column.field]) {
                                originalSetting = tableSetting.width[column.field];
                            } else if (column.colDef.minWidth || column.colDef.width) {
                                needSaveSetting = true;
                                tableSetting = tableSetting || {};
                                originalSetting = tableSetting[column.colDef.field] = {
                                    width: column.colDef.width || column.width,
                                    minWidth: column.colDef.minWidth
                                };
                            }
                            if (tableSetting && tableSetting.width && tableSetting.width['_' + uiGridCtrl.grid.options.displayStyle] && tableSetting.width['_' + uiGridCtrl.grid.options.displayStyle][column.field]) {
                                column.width = tableSetting.width['_' + uiGridCtrl.grid.options.displayStyle][column.field].adjustWidth;
                            } else {
                                column.width = '*';
                            }
                            column.minWidth = column.colDef.minWidth ? 30 : null;
                        }
                    });
                    if (needSaveSetting) {
                        storageService.saveTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_'), {
                            displayStyle: uiGridCtrl.grid.options.displayStyle,
                            width: tableSetting
                        });
                    }
                    uiGridCtrl.grid.refreshCanvas(true).then(function () {
                        angular.forEach(uiGridCtrl.grid._scrollBars, function (scrollbar) {
                            scrollbar.update();
                        });
                    });
                };
                $scope.showNormal = function () {
                    var tableSetting;
                    tableSetting = storageService.getTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_'));
                    angular.forEach(uiGridCtrl.grid.columns, function (column) {
                        var originalSetting;
                        if (column.field && column.name.indexOf('RowHeaderCol') < 0) {
                            if (tableSetting && tableSetting.width && tableSetting.width[column.field]) {
                                originalSetting = tableSetting.width[column.field];
                            }
                            if (tableSetting && tableSetting.width && tableSetting.width['_' + uiGridCtrl.grid.options.displayStyle] && tableSetting.width['_' + uiGridCtrl.grid.options.displayStyle][column.field]) {
                                column.colDef.width = tableSetting.width['_' + uiGridCtrl.grid.options.displayStyle][column.field].adjustWidth;
                            } else if (originalSetting) {
                                column.colDef.width = originalSetting.width;
                            }
                            column.colDef.minWidth = originalSetting ? originalSetting.minWidth : column.colDef.minWidth;
                        }
                    });
                    uiGridCtrl.grid.refreshCanvas(true).then(function () {
                        angular.forEach(uiGridCtrl.grid._scrollBars, function (scrollbar) {
                            scrollbar.update('mouseenter');
                        });
                    });
                    uiGridCtrl.grid.api.core.notifyDataChange(uiGridConstants.dataChange.COLUMN);
                };
                $scope.toggleMenu = function () {
                    if ($scope.shown) {
                        $scope.$broadcast('hide-menu');
                        $scope.shown = false;
                    } else {
                        $scope.menuItems = uiGridGridMenuService.getMenuItems($scope);
                        $scope.$broadcast('show-menu');
                        $scope.shown = true;
                    }
                };

                $scope.$on('menu-hidden', function () {
                    $scope.shown = false;
                    gridUtil.focus.bySelector($elm, '.ui-grid-icon-container');
                });
                if (uiGridCtrl.grid.options.displayStyle == 'all') {
                    $scope.showAll();
                } else {
                    $scope.showNormal();
                }
                function gridResize() {
                    uiGridCtrl.grid.gridWidth = gridUtil.elementWidth($elm);
                    uiGridCtrl.grid.gridHeight = gridUtil.elementHeight($elm);
                    uiGridCtrl.grid.refreshCanvas(true);
                }
            }
        };
    }

    uiGridCustomerMenuItem.$inject = ['gridUtil', '$compile', 'i18nService', 'uiGridMoveColumnService', 'uiGridResizeColumnsService', '$injector'];
    function uiGridCustomerMenuItem(gridUtil, $compile, i18nService, uiGridMoveColumnService, uiGridResizeColumnsService, $injector) { // change menu items
        return {
            priority: 0,
            scope: {
                name: '=',
                active: '=',
                action: '=',
                icon: '=',
                shown: '=',
                context: '=',
                templateUrl: '=',
                leaveOpen: '=',
                screenReaderOnly: '=',
                index: '='
            },
            require: ['?^uiGrid'],
            templateUrl: 'ui-grid/uiGridMenuItem',
            replace: false,
            compile: function () {
                return {
                    pre: function ($scope, $elm) {
                        if ($scope.templateUrl) {
                            gridUtil.getTemplate($scope.templateUrl)
                                .then(function (contents) {
                                    var template = angular.element(contents);

                                    var newElm = $compile(template)($scope);
                                    $elm.replaceWith(newElm);
                                }).catch(angular.noop);
                        }
                    },
                    post: function ($scope, $elm, $attrs, controllers) {
                        var uiGridCtrl = controllers[0];

                        $scope.getGrid = function () {
                            return uiGridCtrl.grid;
                        };

                        // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though
                        // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {
                        // throw new TypeError("$scope.shown is defined but not a function");
                        // }
                        if (typeof ($scope.shown) === 'undefined' || $scope.shown === null) {
                            $scope.shown = function () { return true; };
                        }

                        $scope.visible = $scope.context ? $scope.context.gridCol.colDef.visible : undefined;

                        $scope.itemShown = function () {
                            var context = {};
                            if ($scope.context) {
                                context.context = $scope.context;
                            }

                            if (typeof (uiGridCtrl) !== 'undefined' && uiGridCtrl) {
                                context.grid = uiGridCtrl.grid;
                            }

                            return $scope.shown.call(context);
                        };

                        $scope.itemAction = function ($event, title) {
                            $event.stopPropagation();

                            if (typeof ($scope.action) === 'function') {
                                var context = {};

                                if ($scope.context) {
                                    context.context = $scope.context;
                                }

                                // Add the grid to the function call context if the uiGrid controller is present
                                if (typeof (uiGridCtrl) !== 'undefined' && uiGridCtrl) {
                                    context.grid = uiGridCtrl.grid;
                                }
                                $scope.action.call(context, $event, title);
                                adjustColumnWidth();
                                $scope.visible = $scope.context.gridCol.colDef.visible;
                                if ($injector.get('storageService')) {
                                    var visible = {};
                                    visible[$scope.context.gridCol.colDef.field] = $scope.context.gridCol.colDef.visible;
                                    $injector.get('storageService').saveTableSetting(($scope.$root.pageId + ':' + uiGridCtrl.grid.options.name).split('.').join('_'), {
                                        'displayStyle': uiGridCtrl.grid.options.displayStyle,
                                        'visible': visible
                                    });
                                }
                                $scope.$emit(GridConstants.NOTIFY_HIDE_COLUMN);
                                if (!$scope.leaveOpen) {
                                    $scope.$emit('hide-menu');
                                } else {
                                    // Maintain focus on the selected item
									/*var correctParent = $event.target.parentElement;
				
									// nodeName of 'I' means target is i element, need the next parent
									if (angular.element($event.target)[0].nodeName === 'I') {
									  correctParent = correctParent.parentElement;
									}
				
									gridUtil.focus.bySelector(correctParent, 'button[type=button]', true);*/
                                }
                            }
                        };

                        $scope.itemMoved = function ($event) {
                            var i, col, columns;
                            col = $scope.context.gridCol.colDef;
                            columns = uiGridCtrl.grid.columns;
                            if ((angular.isUndefined(col.visible) || col.visible === true)) {
                                for (i = 0; i < columns.length; i++) {
                                    if ((angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) && $scope.context.gridCol.uid == columns[i].uid) {
                                        uiGridMoveColumnService.redrawColumnAtPosition(uiGridCtrl.grid, i, i - 1);
                                        break;
                                    }
                                }
                                uiGridMoveColumnService(uiGridCtrl.grid, index, index - 1);
                            }
                        }

                        $scope.label = function () {
                            var toBeDisplayed = $scope.name;

                            if (typeof ($scope.name) === 'function') {
                                toBeDisplayed = $scope.name.call();
                            }

                            return toBeDisplayed;
                        };

                        $scope.i18n = i18nService.get();

                        function adjustColumnWidth() {
                            //TODU:
                        }
                    }
                };
            }
        }
    }
    uiGridCustomerAutoResize.$inject = ['gridUtil', 'uiGridConstants', '$interval', '$timeout', '$window', '$document', 'ScrollEvent', 'GridConstants'];
    function uiGridCustomerAutoResize(gridUtil, uiGridConstants, $interval, $timeout, $window, $document, ScrollEvent, GridConstants) {
        return {
            require: ['uiGrid', '^?fsTabset'],
            scope: false,
            link: function ($scope, $elm, $attrs, ctrls) {
                var tabIndex, watch, cellsWatch, watchers = [], uiGridCtrl = ctrls[0], tabsetCtrl = ctrls[1], uiGrids = [];
                var resizeTimer, adjustHeightTimer;
                ScrollEvent.prototype.atTop = function (scrollTop) {
                    var viewport = $elm[0].querySelector('.ui-grid-render-container-body .ui-grid-viewport');
                    if (viewport && angular.element(viewport).css('overflow-y') == 'hidden') {
                        return true;
                    }
                    return (this.y && (this.y.percentage === 0 || this.verticalScrollLength < 0) && scrollTop === 0);
                };
                ScrollEvent.prototype.atBottom = function (scrollTop) {
                    var viewport = $elm[0].querySelector('.ui-grid-render-container-body .ui-grid-viewport');
                    if (viewport && angular.element(viewport).css('overflow-y') == 'hidden') {
                        return true;
                    }
                    return (this.y && (this.y.percentage === 1 || this.verticalScrollLength === 0) && scrollTop > 0);
                };
                scrollbarWidth = gridUtil.getScrollbarWidth();
                $scope.$on('$destroy', function () {
                    (cellsWatch || angular.noop)();
                    while (watchers.length) {
                        (watchers.shift() || angular.noop)();
                    }
                });
                watch = $scope.$watchGroup([function () {
                    var bodyWidth = gridUtil.elementWidth($document[0].querySelector('body'));
                    return $window.innerWidth - bodyWidth;
                }], function (newValues, oldValues) {
                    if (!angular.equals(newValues, oldValues)) {
                        gridResize();
                    }
                });
                watchers.push(watch);
                if (tabsetCtrl) {
                    tabIndex = tabsetCtrl.active;
                    watch = $scope.$watch(function () {
                        return tabsetCtrl.active;
                    }, function (active) {
                        if (active == tabIndex) {
                            adjustHeight(uiGridCtrl.grid.renderContainers.body.renderedRows);
                        }
                    });
                    watchers.push(watch);
                }
                angular.element($window).on('resize', function () {
                    if (resizeTimer) {
                        return;
                    }
                    resizeTimer = $interval(function () {
                        var adjustRows = autoAdjustHeight();
                        if (uiGridCtrl.grid.renderContainers.body.renderedRows.length > 0 && adjustRows == uiGridCtrl.grid.renderContainers.body.renderedRows.length) {
                            $interval.cancel(resizeTimer);
                        } else if (!uiGridCtrl.grid.renderContainers.body.renderedRows || uiGridCtrl.grid.renderContainers.body.renderedRows.length == 0) {
                            $interval.cancel(resizeTimer);
                        }
                        resizeTimer = null;
                    }, 0, false);
                });
                watch = $scope.$watchCollection(function () {
                    return uiGridCtrl.grid.renderContainers.body.renderedRows;
                }, function (renderedRows) {
                    adjustHeight(renderedRows);
                });
                watchers.push(watch);
                $scope.$on(GridConstants.NOTIFY_HIDE_COLUMN, function (event, args) {
                    adjustHeight(uiGridCtrl.grid.renderContainers.body.renderedRows);
                    //event.preventDefault();
                    //event.stopPropagation();
                });
                $scope.$on(GridConstants.NOTIFY_COLLPASE_LEFT_MENU, function (event, args) {
                    adjustHeight(uiGridCtrl.grid.renderContainers.body.renderedRows);
                });
                function adjustHeight(newData, oldData) {
                    if (adjustHeightTimer) {
                        return;
                    }
                    adjustHeightTimer = $interval(function () {
                        var adjustRows = autoAdjustHeight();
                        if (newData && newData.length > 0 && adjustRows == newData.length) {
                            $interval.cancel(adjustHeightTimer);
                        } else if (!newData || newData.length == 0) {
                            $interval.cancel(adjustHeightTimer);
                        }
                        adjustHeightTimer = null;
                    }, 0, false);
                }
                function autoAdjustHeight() {
                    var leftCanvas, centerCanvas, rightCanvas, leftRows, centerRows, rightRows, leftGridCanvas, centerGridCanvas, rightGridCanvas, gridViewports, gridColumnFooter, gridFooter, pageBar;
                    var i, e1, e2, e3, cells, cellsWatchGroup, visibleLines = 0, maxHeight, scrollbarHeight = 0, contentHeight = 0, headerHeight = 0, footerHeight = 0, scrollbarHeight = 0, filterHeight = 0, pageBarHeight = 0, maxNumberOfFilters = 0, allColumnsHaveFilteringTurnedOff;
                    var adjustElements = [];
                    if (uiGridCtrl.grid.options.showHeader) {
                        e1 = $elm[0].querySelector(".ui-grid-render-container-left .ui-grid-header-cell-wrapper");
                        e2 = $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-header-cell-wrapper");
                        e3 = $elm[0].querySelector(".ui-grid-render-container-right .ui-grid-header-cell-wrapper");
                        leftCanvas = $elm[0].querySelector(".ui-grid-render-container-left .ui-grid-header-canvas");
                        centerCanvas = $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-header-canvas");
                        rightCanvas = $elm[0].querySelector(".ui-grid-render-container-right .ui-grid-header-canvas");

                        maxHeight = uiGridCtrl.grid.options.headerRowHeight;
                        if (e1) {
                            angular.element(e1).css({ height: 'auto' });
                        }
                        if (e2) {
                            angular.element(e2).css({ height: 'auto' });
                            cells = e2.querySelectorAll('.ui-grid-header-cell');
                            if (cells && cells.length > 0) {
                                cellsWatchGroup = [];
                                angular.forEach(cells, function (cell, i) {
                                    cellsWatchGroup[i] = function () {
                                        return cell.offsetWidth;
                                    }
                                });
                                (cellsWatch || angular.noop)();
                                cellsWatch = $scope.$watchGroup(cellsWatchGroup, function (newValues, oldValues) {
                                    if (!angular.equals(newValues, oldValues)) {
                                        adjustHeight(uiGridCtrl.grid.renderContainers.body.renderedRows);
                                    }
                                });
                            }
                        }
                        if (e3) {
                            angular.element(e3).css({ height: 'auto' });
                        }
                        if (leftCanvas) {
                            angular.element(leftCanvas).css({ height: 'auto' });
                        }
                        if (centerCanvas) {
                            angular.element(centerCanvas).css({ height: 'auto' });
                        }
                        if (rightCanvas) {
                            angular.element(rightCanvas).css({ height: 'auto' });
                        }
                        maxHeight = Math.max(maxHeight, e1 ? e1.offsetHeight : 0, e2 ? e2.offsetHeight : 0, e3 ? e3.offsetHeight : 0);
                        headerHeight += maxHeight;
                        if (e1) {
                            angular.element(e1).css({ height: maxHeight + 'px' });
                        }
                        if (e2) {
                            angular.element(e2).css({ height: maxHeight + 'px' });
                        }
                        if (e3) {
                            angular.element(e3).css({ height: maxHeight + 'px' });
                        }
						/*if (leftCanvas) {
							angular.element(leftCanvas).css({ height : headerHeight + 'px' });
						}
						if (centerCanvas) {
							angular.element(centerCanvas).css({ height : headerHeight + 'px' });
						}
						if (rightCanvas) {
							angular.element(rightCanvas).css({ height : headerHeight + 'px' });
						}*/
                    }
                    gridViewports = $elm[0].querySelectorAll('.ui-grid-viewport');
                    if (!gridViewports || gridViewports.length == 0) {
                        return 0;
                    }
                    leftGridCanvas = $elm[0].querySelector(".ui-grid-render-container-left .ui-grid-viewport .ui-grid-canvas");
                    centerGridCanvas = $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport .ui-grid-canvas");
                    rightGridCanvas = $elm[0].querySelector(".ui-grid-render-container-right .ui-grid-viewport .ui-grid-canvas");
                    leftRows = leftGridCanvas ? leftGridCanvas.querySelectorAll(".grid-row") : undefined;
                    centerRows = centerGridCanvas ? centerGridCanvas.querySelectorAll(".grid-row") : undefined;
                    rightRows = rightGridCanvas ? rightGridCanvas.querySelectorAll(".grid-row") : undefined;
                    for (i = 0; centerRows && i < centerRows.length; i++) {
                        e1 = leftRows ? leftRows[i] : undefined;
                        e2 = centerRows ? centerRows[i] : undefined;
                        e3 = rightRows ? rightRows[i] : undefined;
                        maxHeight = uiGridCtrl.grid.options.rowHeight;
                        if (e1) {
                            angular.element(e1).css({ height: 'auto' });
                        }
                        if (e2) {
                            angular.element(e2).css({ height: 'auto' });
                        }
                        if (e3) {
                            angular.element(e3).css({ height: 'auto' });
                        }
                        maxHeight = Math.max(maxHeight, e1 ? e1.offsetHeight : 0, e2 ? e2.offsetHeight : 0, e3 ? e3.offsetHeight : 0);
                        if (uiGridCtrl.grid.options.maxRowsToShow > 0) {
                            if (i < uiGridCtrl.grid.options.maxRowsToShow) {
                                visibleLines++;
                                contentHeight += maxHeight;
                            }
                        } else if (i < uiGridCtrl.grid.options.paginationPageSize || uiGridCtrl.grid.options.enableVerticalScrollbar == uiGridConstants.scrollbars.NEVER) {
                            visibleLines++;
                            contentHeight += maxHeight;
                        }
                        if (e1) {
                            adjustElements.push({ element: angular.element(e1), height: maxHeight });
                        }
                        if (e2) {
                            adjustElements.push({ element: angular.element(e2), height: maxHeight });
                        }
                        if (e3) {
                            adjustElements.push({ element: angular.element(e3), height: maxHeight });
                        }
                    }

                    if (uiGridCtrl.grid.options.minRowsToShow && i < uiGridCtrl.grid.options.minRowsToShow) {
                        visibleLines += (uiGridCtrl.grid.options.minRowsToShow - i);
                        contentHeight += uiGridCtrl.grid.options.rowHeight * (uiGridCtrl.grid.options.minRowsToShow - i);
                    }

                    angular.forEach(adjustElements, function (elm, height) {
                        elm.element.css({ height: elm.height + 'px' });
                    });

                    if (!contentHeight) {
                        angular.element(centerGridCanvas).css({
                            height: uiGridCtrl.grid.options.rowHeight + 'px'
                        });
                    } else {
                        angular.element(centerGridCanvas).css({
                            height: 'auto'
                        });
                    }

                    contentHeight = contentHeight ? contentHeight : uiGridCtrl.grid.options.rowHeight;
                    contentHeight += (visibleLines ? visibleLines : 0);
                    footerHeight = uiGridCtrl.grid.calcFooterHeight();
                    if (needsHScrollbarPlaceholder()) {
                        scrollbarHeight = uiGridCtrl.grid.scrollbarHeight;
                    }
                    if ($elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport .ps__thumb-x") && $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport .ps__thumb-x").offsetHeight > 0) {
                        contentHeight += $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport .ps__thumb-x").offsetHeight + 2;
                    }
                    angular.forEach(uiGridCtrl.grid.options.columnDefs, function (col) {
                        if (col.hasOwnProperty('filter')) {
                            if (maxNumberOfFilters < 1) {
                                maxNumberOfFilters = 0;
                            }
                        } else if (col.hasOwnProperty('filters')) {
                            if (maxNumberOfFilters < col.filters.length) {
                                maxNumberOfFilters = col.filters.length;
                            }
                        }
                    });

                    if (uiGridCtrl.grid.options.enableFiltering && !maxNumberOfFilters) {
                        allColumnsHaveFilteringTurnedOff = uiGridCtrl.grid.options.columnDefs.length && uiGridCtrl.grid.options.columnDefs.every(function (col) {
                            return col.enableFiltering === false;
                        });
                        if (!allColumnsHaveFilteringTurnedOff) {
                            maxNumberOfFilters = 1;
                        }
                    }

                    filterHeight = maxNumberOfFilters * (uiGridCtrl.grid.options.showHeader ? uiGridCtrl.grid.options.headerRowHeight : 0);

                    pageBar = $elm[0].querySelector(".ui-grid-pager-panel");
                    if (pageBar) {
                        pageBarHeight = gridUtil.elementHeight(angular.element(pageBar));
                    }
                    //var h = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight + pageBarHeight;
                    var gridViewport = $elm[0].querySelector(".ui-grid-render-container-left .ui-grid-viewport");
                    if (gridViewport && angular.element(gridViewport).css("height") != (contentHeight + 'px')) {
                        angular.element(gridViewport).css({ height: contentHeight + 'px' });
                        angular.element(gridViewport.querySelector(".scroller")).css({ height: contentHeight + 'px' });
                    }
                    gridViewport = $elm[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport");
                    if (gridViewport && angular.element(gridViewport).css("height") != ((contentHeight + scrollbarHeight) + 'px')) {
                        angular.element(gridViewport).css({ height: (contentHeight + scrollbarHeight) + 'px' });
                        angular.element(gridViewport.querySelector(".scroller")).css({ height: (contentHeight + scrollbarHeight) + 'px' });
                        $scope.$broadcast('scrollbar-resize');
                    }
                    gridViewport = $elm[0].querySelector(".ui-grid-render-container-right .ui-grid-viewport");
                    if (gridViewport && angular.element(gridViewport).css("height") != (contentHeight + 'px')) {
                        angular.element(gridViewport).css({ height: contentHeight + 'px' });
                        angular.element(gridViewport.querySelector(".scroller")).css({ height: contentHeight + 'px' });
                    }

					/*if (uiGridCtrl.grid.options.enablePagination && uiGridCtrl.grid.options.enablePaginationControls) {
						h += (visibleLines ? visibleLines : 0);
					}*/
                    if ($elm.css("height") != 'auto') {
                        $elm.css('height', 'auto');
                    }
                    $timeout(function () {
                        gridResize();
                    }, 200);

                    return centerRows ? centerRows.length : 0;
                }

                function gridResize() {
                    uiGridCtrl.grid.gridWidth = gridUtil.elementWidth($elm);
                    uiGridCtrl.grid.gridHeight = gridUtil.elementHeight($elm);
                    uiGridCtrl.grid.refreshCanvas(true);
                }

                function needsHScrollbarPlaceholder() {
                    var self = uiGridCtrl, containerBody;
                    if (self.grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
                        return true;
                    }
                    containerBody = $elm[0].querySelector('.ui-grid-render-container-body .ui-grid-viewport');
                    return containerBody.scrollWidth > containerBody.offsetWidth;
                }
            }
        };
    }

    uiGridCustomerPagination.$inject = ['gridUtil', 'uiGridPaginationService'];
    function uiGridCustomerPagination(gridUtil, uiGridPaginationService) {
        return {
            priority: -200,
            scope: false,
            require: 'uiGrid',
            link: {
                pre: function ($scope, $elm, $attr, uiGridCtrl) {
                    uiGridPaginationService.initializeGrid(uiGridCtrl.grid);

                    var paginationPageSizesArray = uiGridCtrl.grid.options.paginationPageSizes;
                    var newPaginationPageSizesOptions = [];
                    for (var i = 0; i < paginationPageSizesArray.length; i++) {
                        newPaginationPageSizesOptions.push({ 'label': paginationPageSizesArray[i], 'value': paginationPageSizesArray[i] });
                    }
                    uiGridCtrl.paginationPageSizeChanged = function (obj, formCtrl, isInitialized) {
                        if (isInitialized) return;
                        uiGridCtrl.grid.options.paginationPageSize = obj.paginationPageSize;
                    }
                    uiGridCtrl.grid.options.paginationPageSizeGridObj = {
                        "name": "paginationPageSize",
                        "label": "",
                        "model": "paginationPageSize",
                        "type": "customer-select",
                        "template": "normal",
                        "options": {
                            "filterable": false,
                            "hasEmptyOption": false,
                            "appendToBody": false,
                            "data": newPaginationPageSizesOptions,
                            "callback": {
                                "changed": uiGridCtrl.paginationPageSizeChanged
                            }
                        }
                    };
                    if (!uiGridCtrl.grid.options.paginationPageSizeGridObj.paginationPageSize) {
                        uiGridCtrl.grid.options.paginationPageSizeGridObj.paginationPageSize = uiGridCtrl.grid.options.paginationPageSize;
                    }

                    gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)
                        .then(function (contents) {
                            var template = angular.element(contents);
                            if (uiGridCtrl.grid.options.paginationStyle == 'before') {
                                $elm.prepend(template);
                            }
                            if (!uiGridCtrl.grid.options.paginationStyle || uiGridCtrl.grid.options.paginationStyle == 'after') {
                                $elm.append(template);
                            }
                            uiGridCtrl.innerCompile(template);
                        });
                }
            }
        };
    }

    uiGridOperationService.$inject = [];
    function uiGridOperationService() {
        var service = {
            initializeGrid: function (grid) {
                service.defaultGridOptions(grid.options);
            },
            defaultGridOptions: function (gridOptions) {
                gridOptions.enableOperation = gridOptions.enableOperation === true;
                gridOptions.enableOperationAdd = gridOptions.addRow ? true : false;
                gridOptions.enableOperationRemoveSelected = gridOptions.enableOperationRemoveSelected !== false;
                gridOptions.enableOperationRemoveAll = gridOptions.enableOperationRemoveAll !== false;
                gridOptions.enableOperationView = gridOptions.viewRow ? true : false;
                gridOptions.enableOperationEdit = gridOptions.editRow ? true : false;
                gridOptions.enableOperationCancel = gridOptions.cancelRow ? true : false;
                gridOptions.enableOperationAddSubRow = gridOptions.addSubRow ? true : false;
                gridOptions.enableOperationRemove = gridOptions.removeRow ? true : false;
                gridOptions.enableOperationProcess = gridOptions.processRow ? true : false;
                gridOptions.enableOperationMoreProcess = gridOptions.moreProcess ? true : false;
                gridOptions.viewRowPermission = gridOptions.viewRowPermission ? gridOptions.viewRowPermission : "*";
                gridOptions.editRowPermission = gridOptions.editRowPermission ? gridOptions.editRowPermission : "*";
                gridOptions.cancelRowPermission = gridOptions.cancelRowPermission ? gridOptions.cancelRowPermission : "*";
                gridOptions.downloadRowPermission = gridOptions.downloadRowPermission ? gridOptions.downloadRowPermission : "*";
                gridOptions.addSubRowPermission = gridOptions.addSubRowPermission ? gridOptions.addSubRowPermission : "*";
                gridOptions.removeRowPermission = gridOptions.removeRowPermission ? gridOptions.removeRowPermission : "*";
                gridOptions.processRowPermission = gridOptions.processRowPermission ? gridOptions.processRowPermission : "*";

                gridOptions.enableEolOperation = gridOptions.enableEolOperation === true;
                gridOptions.enableEolOperationView = gridOptions.viewRowByEol ? true : false;
                gridOptions.enableEolOperationEdit = gridOptions.editRowByEol ? true : false;
                gridOptions.enableEolOperationCancel = gridOptions.cancelRowByEol ? true : false;
                gridOptions.enableEolOperationDownload = gridOptions.downloadRowByEol ? true : false;
                gridOptions.enableEolOperationAddSubRow = gridOptions.addSubRowByEol ? true : false;
                gridOptions.enableEolOperationRemove = gridOptions.removeRowByEol ? true : false;
                gridOptions.enableEolOperationProcess = gridOptions.processRowByEol ? true : false;
                gridOptions.enableEolOperationMoreProcess = gridOptions.moreProcessByEol ? true : false;
                gridOptions.viewRowByEolPermission = gridOptions.viewRowByEolPermission ? gridOptions.viewRowByEolPermission : "*";
                gridOptions.editRowByEolPermission = gridOptions.editRowByEolPermission ? gridOptions.editRowByEolPermission : "*";
                gridOptions.cancelRowByEolPermission = gridOptions.cancelRowByEolPermission ? gridOptions.cancelRowByEolPermission : "*";
                gridOptions.downloadRowByEolPermission = gridOptions.downloadRowByEolPermission ? gridOptions.downloadRowByEolPermission : "*";
                gridOptions.addSubRowByEolPermission = gridOptions.addSubRowByEolPermission ? gridOptions.addSubRowByEolPermission : "*";
                gridOptions.removeRowByEolPermission = gridOptions.removeRowByEolPermission ? gridOptions.removeRowByEolPermission : "*";
                gridOptions.processRowByEolPermission = gridOptions.processRowByEolPermission ? gridOptions.processRowByEolPermission : "*";
            }
        };
        return service;
    }

    uiGridOperation.$inject = ['uiGridOperationService'];
    function uiGridOperation(uiGridOperationService) {
        return {
            replace: true,
            priority: 0,
            require: '^uiGrid',
            scope: false,
            compile: function () {
                return {
                    pre: function ($scope, $elm, $attrs, uiGridCtrl) {
                        var self = uiGridCtrl.grid;
                        uiGridOperationService.initializeGrid(self);
                        if (self.options.enableOperation) {
                            var operationRowHeaderDef = {
                                name: 'operationRowHeaderCol',
                                displayName: '',
                                width: calculateWidth(),
                                minWidth: 10,
                                cellTemplate: 'pti/operationRowHeader',
                                headerCellTemplate: 'pti/operationHeaderCell',
                                enableColumnResizing: false,
                                enableColumnMenu: false,
                                exporterSuppressExport: true,
                                allowCellFocus: true
                            };

                            self.addRowHeaderColumn(operationRowHeaderDef, -10);
                        }

                        function calculateWidth() {
                            var width = 30, btnSize = 0;
                            if (angular.isDefined(self.options.operationRowHeaderWidth)) {
                                return self.options.operationRowHeaderWidth;
                            }
                            if (self.options.enableOperationView) {
                                btnSize++;
                            }
                            if (self.options.enableOperationEdit) {
                                btnSize++;
                            }
                            if (self.options.enableOperationCancel) {
                                btnSize++;
                            }
                            if (self.options.enableOperationDownload) {
                                btnSize++;
                            }
                            if (self.options.enableOperationAddSubRow) {
                                btnSize++;
                            }
                            if (self.options.enableOperationRemove) {
                                btnSize++;
                            }
                            if (self.options.enableOperationProcess) {
                                btnSize++;
                            }
                            if (self.options.enableOperationMoreProcess) {
                                btnSize++;
                            }
                            return width + ((btnSize - 1) >= 0 ? (btnSize - 1) : 0) * 20;
                        }
                    },
                    post: function ($scope, $elm, $attrs, uiGridCtrl) {

                    }
                };
            }
        };
    }

    uiGridEolOperation.$inject = ['uiGridOperationService', 'GridColumn', 'gridUtil'];
    function uiGridEolOperation(uiGridOperationService, GridColumn, gridUtil) {
        function eolOperationBuilder(colDef, col, gridOptions) {
            if (colDef.pinnedLeft) {
                col.grid.createRightContainer();
            } else if (colDef.pinnedRight) {
                col.grid.createLeftContainer();
            }
        }
        function addReverseOperationRowHeaderColumn(grid, colDef, order, stopColumnBuild) {
            var self = grid;

            // default order
            if (order === undefined) {
                order = 0;
            }

            var rowHeaderCol = new GridColumn(colDef, gridUtil.nextUid(), self);
            rowHeaderCol.isRowHeader = true;
            if (self.isRTL()) {
                self.createLeftContainer();
                rowHeaderCol.renderContainer = 'left';
            }
            else {
                self.createRightContainer();
                rowHeaderCol.renderContainer = 'right';
            }

            // relies on the default column builder being first in array, as it is instantiated as part of grid creation
            self.columnBuilders[0](colDef, rowHeaderCol, self.options)
                .then(function () {
                    rowHeaderCol.enableFiltering = false;
                    rowHeaderCol.enableSorting = false;
                    rowHeaderCol.enableHiding = false;
                    rowHeaderCol.headerPriority = order;
                    self.rowHeaderColumns.push(rowHeaderCol);
                    self.rowHeaderColumns = self.rowHeaderColumns.sort(function (a, b) {
                        return a.headerPriority - b.headerPriority;
                    });

                    if (!stopColumnBuild) {
                        self.buildColumns().then(function () {
                            self.preCompileCellTemplates();
                            self.queueGridRefresh();
                        }).catch(angular.noop);
                    }
                }).catch(angular.noop);
        }
        return {
            replace: true,
            priority: 0,
            require: '^uiGrid',
            scope: false,
            compile: function () {
                return {
                    pre: function ($scope, $elm, $attrs, uiGridCtrl) {
                        var self = uiGridCtrl.grid;
                        if (self.options.enableEolOperation) {
                            self.registerColumnBuilder(eolOperationBuilder);
                            uiGridOperationService.initializeGrid(self);
                            var operationRowHeaderDef = {
                                name: 'eolOperationRowHeaderCol',
                                displayName: 'list.title.action',
                                width: calculateWidth(),
                                minWidth: 30,
                                cellTemplate: 'pti/eolOperationRowHeader',
                                headerCellTemplate: "<div role=\"columnheader\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\"><span class=\"ui-grid-header-cell-label\">{{ col.displayName | translate }}</span></div></div>",
                                enableColumnResizing: false,
                                enableColumnMenu: false,
                                exporterSuppressExport: true,
                                allowCellFocus: true,
                                pinnedRight: true
                            };
                            addReverseOperationRowHeaderColumn(self, operationRowHeaderDef, -10);
                        }

                        function calculateWidth() {
                            var width = 75, btnSize = 0;
                            if (angular.isDefined(self.options.operationRowHeaderWidth)) {
                                return self.options.operationRowHeaderWidth;
                            }
                            if (self.options.enableEolOperationView) {
                                btnSize++;
                            }
                            if (self.options.enableEolOperationEdit) {
                                btnSize++;
                            }
                            if (self.options.enableEolOperationCancel) {
                                btnSize++;
                            }
                            if (self.options.enableEolOperationDownload) {
                                btnSize++;
                            }
                            if (self.options.enableEolOperationAddSubRow) {
                                btnSize++;
                            }
                            if (self.options.enableEolOperationRemove) {
                                btnSize++;
                            }
                            if (self.options.enableEolOperationProcess) {
                                btnSize++;
                            }
                            if (self.options.enableEolOperationMoreProcess) {
                                btnSize++;
                            }
                            return width + ((btnSize - 2) >= 0 ? (btnSize - 2) : 0) * 20;
                        }
                    },
                    post: function ($scope, $elm, $attrs, uiGridCtrl) {

                    }
                };
            }
        };
    }

    uiGridOperationRowHeaderButtons.$inject = ['$templateCache', 'uiGridSelectionService', '$timeout'];
    function uiGridOperationRowHeaderButtons($templateCache, uiGridSelectionService, $timeout) {
        return {
            replace: true,
            restrict: 'E',
            template: function ($elm, $attrs) {
                var isEolOprarion = $attrs.eol == undefined ? false : true;
                if (isEolOprarion) {
                    return $templateCache.get('pti/eolOperationRowHeaderButtons');
                }
                return $templateCache.get('pti/operationRowHeaderButtons');
            },
            scope: true,
            require: '^uiGrid',
            link: function ($scope, $elm, $attrs, uiGridCtrl) {
                var self = uiGridCtrl.grid, watchers = [], watcher, authorization;
                var isEolOprarion = $attrs.eol == undefined ? false : true;
                $scope.$on('$destroy', function () {
                    while (watchers.length) {
                        (watchers.shift() || angular.noop)();
                    }
                });
                $scope.disableElement = function ($event) {
                    var btn = ($event.srcElement || $event.target).parentElement;
                    if (btn.disabled) {
                        return false;
                    }
                    btn.disabled = true;
                    $timeout(function () {
                        btn.disabled = false;
                    }, 1000);
                };
                authorization = self.appScope ? (self.appScope.authorization || ((self.appScope.$stateParams) ? self.appScope.$stateParams.authorization : null)) : null;
                initFilterRowOperationCallBack();
                initViewButtonClickCallBack();
                initEditButtonClickCallBack();
                initCancelButtonClickCallBack();
                initDownloadButtonClickCallBack();
                initAddSubRowButtonClickCallBack();
                initRemoveButtonClickCallBack();
                initProcessButtonClickCallBack();
                function initFilterRowOperationCallBack() {
                    if (self.options.filterRowOperation) {
                        if (angular.isString(self.options.filterRowOperation)) {
                            watcher = self.appScope.$watch(self.options.filterRowOperation, function (filterRowOperation) {
                                $scope.filterRowOperation = function (row, operation) {
                                    if (angular.isFunction(filterRowOperation)) {
                                        return filterRowOperation(row, operation);
                                    } else {
                                        return false;
                                    }
                                }
                            });
                            watchers.push(watcher);
                        } else if (angular.isFunction(self.options.filterRowOperation)) {
                            $scope.filterRowOperation = function (row, operation) {
                                return self.options.filterRowOperation(row, operation);
                            }
                        } else {
                            return false;
                        }
                    } else {
                        $scope.filterRowOperation = function (row, operation) {
                            return false;
                        }
                    }
                }

                function initViewButtonClickCallBack() {
                    var viewPermission = isEolOprarion ? self.options.viewRowByEolPermission : self.options.viewRowPermission;
                    $scope.viewPermission = {
                        permission: viewPermission,
                        authorization: authorization
                    }
                    var callback = isEolOprarion ? self.options.viewRowByEol : self.options.viewRow;
                    if (callback && angular.isString(callback)) {
                        $scope.viewButtonClick = angular.noop;
                        watcher = self.appScope.$watch(callback, function (view) {
                            $scope.viewButtonClick = function (row, $event) {
                                (view || angular.noop)(row);
                            };
                        });
                        watchers.push(watcher);
                    } else if (angular.isFunction(callback)) {
                        $scope.viewButtonClick = function (row, $event) {
                            callback(row);
                        };
                    } else {
                        $scope.viewButtonClick = angular.noop;
                    }
                }

                function initEditButtonClickCallBack() {
                    var editPermission = isEolOprarion ? self.options.editRowByEolPermission : self.options.editRowPermission;
                    $scope.editPermission = {
                        permission: editPermission,
                        authorization: authorization
                    }
                    var callback = isEolOprarion ? self.options.editRowByEol : self.options.editRow;
                    if (callback && angular.isString(callback)) {
                        $scope.editButtonClick = angular.noop;
                        watcher = self.appScope.$watch(callback, function (edit) {
                            $scope.editButtonClick = function (row, $event) {
                                (edit || angular.noop)(row);
                            };
                        });
                        watchers.push(watcher);
                    } else if (angular.isFunction(callback)) {
                        $scope.editButtonClick = function (row, $event) {
                            callback(row);
                        };
                    } else {
                        $scope.editButtonClick = angular.noop;
                    }
                }

                function initCancelButtonClickCallBack() {
                    var cancelPermission = isEolOprarion ? self.options.cancelRowByEolPermission : self.options.cancelRowPermission;
                    $scope.cancelPermission = {
                        permission: cancelPermission,
                        authorization: authorization
                    }
                    var callback = isEolOprarion ? self.options.cancelRowByEol : self.options.cancelRow;
                    if (callback && angular.isString(callback)) {
                        $scope.cancelButtonClick = angular.noop;
                        watcher = self.appScope.$watch(callback, function (cancel) {
                            $scope.cancelButtonClick = function (row, $event) {
                                (cancel || angular.noop)(row);
                            };
                        });
                        watchers.push(watcher);
                    } else if (angular.isFunction(callback)) {
                        $scope.cancelButtonClick = function (row, $event) {
                            callback(row);
                        };
                    } else {
                        $scope.cancelButtonClick = angular.noop;
                    }
                }

                function initDownloadButtonClickCallBack() {
                    var downloadPermission = isEolOprarion ? self.options.downloadRowByEolPermission : self.options.downloadRowPermission;
                    $scope.downloadPermission = {
                        permission: downloadPermission,
                        authorization: authorization
                    }
                    var callback = isEolOprarion ? self.options.downloadRowByEol : self.options.downloadRow;
                    if (callback && angular.isString(callback)) {
                        $scope.downloadButtonClick = angular.noop;
                        watcher = self.appScope.$watch(callback, function (download) {
                            $scope.downloadButtonClick = function (row, $event) {
                                (download || angular.noop)(row);
                            };
                        });
                        watchers.push(watcher);
                    } else if (angular.isFunction(callback)) {
                        $scope.downloadButtonClick = function (row, $event) {
                            callback(row);
                        };
                    } else {
                        $scope.downloadButtonClick = angular.noop;
                    }
                }

                function initAddSubRowButtonClickCallBack() {
                    var addSubPermission = isEolOprarion ? self.options.addSubRowByEolPermission : self.options.addSubRowPermission;
                    $scope.addSubPermission = {
                        permission: addSubPermission,
                        authorization: authorization
                    }
                    var callback = isEolOprarion ? self.options.addSubRowByEol : self.options.addSubRow;
                    if (callback && angular.isString(callback)) {
                        $scope.addSubRowButtonClick = angular.noop;
                        watcher = self.appScope.$watch(callback, function (addSubRow) {
                            $scope.addSubRowButtonClick = function (row, $event) {
                                (addSubRow || angular.noop)(row);
                            };
                        });
                        watchers.push(watcher);
                    } else if (angular.isFunction(callback)) {
                        $scope.addSubRowButtonClick = function (row, $event) {
                            callback(row);
                        };
                    } else {
                        $scope.addSubRowButtonClick = angular.noop;
                    }
                }

                function initRemoveButtonClickCallBack() {
                    var removePermission = isEolOprarion ? self.options.removeRowByEolPermission : self.options.removeRowPermission;
                    $scope.removePermission = {
                        permission: removePermission,
                        authorization: authorization
                    }
                    var callback = isEolOprarion ? self.options.removeRowByEol : self.options.removeRow;
                    if (callback && angular.isString(callback)) {
                        $scope.removeButtonClick = angular.noop;
                        watcher = self.appScope.$watch(callback, function (remove) {
                            $scope.removeButtonClick = function (row, $event) {
                                var promise = (remove || angular.noop)(row);
                                if (promise && angular.isFunction(promise.then)) {
                                    promise.then(function () {
                                        removeRow(row, $event);
                                    });
                                } else {
                                    removeRow(row, $event);
                                }
                                self.appScope.$emit('REMOVE_ROWS', [row]);
                            };
                        });
                        watchers.push(watcher);
                    } else if (angular.isFunction(callback)) {
                        $scope.removeButtonClick = function (row, $event) {
                            var promise = callback(row);
                            if (promise && angular.isFunction(promise.then)) {
                                promise.then(function () {
                                    removeRow(row, $event);
                                });
                            } else {
                                removeRow(row, $event);
                            }
                            self.appScope.$emit('REMOVE_ROWS', [row]);
                        };
                    } else {
                        $scope.removeButtonClick = function (row, $event) {
                            removeRow(row, $event);
                            self.appScope.$emit('REMOVE_ROWS', [row]);
                        }
                    }
                }

                function initProcessButtonClickCallBack() {
                    var processPermission = isEolOprarion ? self.options.processRowByEolPermission : self.options.processRowPermission;
                    $scope.processPermission = {
                        permission: processPermission,
                        authorization: authorization
                    }
                    var callback = isEolOprarion ? self.options.processRowByEol : self.options.processRow;
                    if (callback && angular.isString(callback)) {
                        $scope.processButtonClick = angular.noop;
                        watcher = self.appScope.$watch(callback, function (process) {
                            $scope.processButtonClick = function (row, $event) {
                                (process || angular.noop)(row);
                                self.appScope.$emit('REMOVE_ROWS', [row]);
                            };
                        });
                        watchers.push(watcher);
                    } else if (angular.isFunction(callback)) {
                        $scope.processButtonClick = function (row, $event) {
                            callback(row);
                            self.appScope.$emit('REMOVE_ROWS', [row]);
                        };
                    } else {
                        $scope.processButtonClick = function (row, $event) {
                            self.appScope.$emit('REMOVE_ROWS', [row]);
                        }
                    }
                }
                $scope.moreProcessPermission = function (processConfig) {
                    $scope.permission = {
                        permission: processConfig.permission,
                        authorization: authorization
                    };
                };
                $scope.moreProcessClick = function (row, processConfig, $event) {
                    var callback = processConfig.callback;
                    if (callback && angular.isString(callback)) {
                        callback = self.appScope.$eval(callback);
                    }
                    if (angular.isFunction(callback)) {
                        callback(row);
                    }
                };
                function removeRow(row, $event) {
                    var selectedRows;
                    if (row !== null && row.isSelected) {
                        uiGridSelectionService.toggleRowSelection(self, row, $event, self.options.multiSelect, self.options.noUnselect);
                    }
                    removeItem(self.options.data, row.entity);
                    selectedRows = getSelectedRows();
                    if (selectedRows && selectedRows.length > 0 && selectedRows[0].isSelected) {
                        uiGridSelectionService.toggleRowSelection(self, selectedRows[0], $event, self.options.multiSelect, self.options.noUnselect);
                        $timeout(function () {
                            uiGridSelectionService.toggleRowSelection(self, selectedRows[0], $event, self.options.multiSelect, self.options.noUnselect);
                        });
                    }
                }

                function getSelectedRows() {
                    return self.rows.filter(function (row) {
                        return row.isSelected;
                    });
                }

                function removeItem(data, item) {
                    var scope, items;
                    if (angular.isString(self.options.data)) {
                        if (self.options.data.match(/ngModel\..*/)) {
                            scope = getNgModelScope($scope);
                        } else {
                            scope = self.appScope;
                        }
                        items = scope.$eval(self.options.data);
                    } else {
                        items = data;
                    }
                    angular.forEach(items, function (row, index) {
                        if (self.options.rowEquality(row, item) || (row.primaryKey == item.primaryKey && item.primaryKey != undefined)) {
                            if (!(row && row.dataStatus) || 'C' == row.dataStatus) {
                                items.splice(index, 1);
                            } else {
                                items[index].dataStatus = 'D';
                            }
                        }
                    });
                }

                function getNgModelScope(scope) {
                    if (!scope) {
                        return null;
                    }
                    if (scope.hasOwnProperty('ngModel')) {
                        return scope;
                    } else {
                        return getNgModelScope(scope.$parent);
                    }
                }
            }
        };
    }

    uiGridOperationHeaderButtons.$inject = ['$templateCache', '$timeout', 'uiGridGroupingService', 'uiGridSelectionService', 'modalService'];
    function uiGridOperationHeaderButtons($templateCache, $timeout, uiGridGroupingService, uiGridSelectionService, modalService) {
        return {
            replace: true,
            restrict: 'E',
            template: $templateCache.get('pti/operationHeaderButtons'),
            scope: true,
            link: function ($scope, $elm, $attrs, uiGridCtrl) {
                var self = $scope.col.grid;
                var watchers = [], watcher;
                $scope.$on('$destroy', function () {
                    while (watchers.length) {
                        (watchers.shift() || angular.noop)();
                    }
                });
                if (self.options.addRow && angular.isString(self.options.addRow)) {
                    $scope.addButtonClick = angular.noop;
                    watcher = self.appScope.$watch(self.options.addRow, function (add) {
                        $scope.addButtonClick = function ($event) {
                            $scope.disableElement($event);
                            var promise, row = { dataStatus: 'C' };
                            if (!angular.isFunction(add)) {
                                _addRow(self.options.data, row);
                                return;
                            }
                            promise = (add || angular.noop)(row);
                            if (promise && angular.isFunction(promise.then)) {
                                promise.then(function () {
                                    _addRow(self.options.data, row);
                                });
                            } else {
                                _addRow(self.options.data, row);
                            }
                            self.appScope.$emit('ADD_ROW', row);
                        };
                        self.options.__addRow = $scope.addButtonClick;
                    });
                    watchers.push(watcher);
                } else if (angular.isFunction(self.options.addRow)) {
                    $scope.addButtonClick = function ($event) {
                        $scope.disableElement($event);
                        var row = { dataStatus: 'C' };
                        var promise = self.options.addRow(row);
                        if (promise && angular.isFunction(promise.then)) {
                            promise.then(function () {
                                _addRow(self.options.data, row);
                            });
                        } else {
                            _addRow(self.options.data, row);
                        }
                        self.appScope.$emit('ADD_ROW', row);
                    };
                    self.options.__addRow = $scope.addButtonClick;
                } else {
                    $scope.addButtonClick = function ($event) {
                        $scope.disableElement($event);
                        var row = { dataStatus: 'C' };
                        _addRow(self.options.data, row);
                        self.appScope.$emit('ADD_ROW', row);
                    };
                    self.options.__addRow = $scope.addButtonClick;
                }

                if (self.options.removeAllRows && angular.isString(self.options.removeAllRows)) {
                    $scope.removeAllButtonClick = angular.noop;
                    watcher = self.appScope.$watch(self.options.removeAllRows, function (removeAll) {
                        $scope.removeAllButtonClick = function ($event) {
                            var promise;
                            if (!angular.isFunction(removeAll)) {
                                removeAllRows($event);
                                return;
                            }
                            promise = (removeAll || angular.noop)();
                            if (promise && angular.isFunction(promise.then)) {
                                promise.then(function () {
                                    removeAllRows($event);
                                });
                            } else {
                                removeAllRows($event);
                            }
                            self.appScope.$emit('REMOVE_ROWS', getAllRows());
                        };
                    });
                    watchers.push(watcher);
                } else if (angular.isFunction(self.options.removeAllRows)) {
                    $scope.removeAllButtonClick = function ($event) {
                        var promise;
                        promise = self.options.removeAllRows();
                        if (promise && angular.isFunction(promise.then)) {
                            promise.then(function () {
                                removeAllRows($event);
                            });
                        } else {
                            removeAllRows($event);
                        }
                        self.appScope.$emit('REMOVE_ROWS', getAllRows());
                    };
                } else {
                    $scope.removeAllButtonClick = function ($event) {
                        removeAllRows($event);
                        self.appScope.$emit('REMOVE_ROWS', getAllRows());
                    }
                }

                if (self.options.removeSelectedRows && angular.isString(self.options.removeSelectedRows)) {
                    $scope.removeSelectedButtonClick = angular.noop;
                    watcher = self.appScope.$watch(self.options.removeSelectedRows, function (removeSelected) {
                        $scope.removeSelectedButtonClick = function ($event) {
                            var promise, selectedRows = getSelectedRows();
                            if (!selectedRows || selectedRows.length == 0) {
                                modalService.openErrorDialogs({
                                    messages: ['title.dialogs.info.norecsel']
                                });
                                return false;
                            }
                            if (!angular.isFunction(removeSelected)) {
                                removeSelectedRows($event);
                                return;
                            }
                            promise = (removeSelected || angular.noop)();
                            if (promise && angular.isFunction(promise.then)) {
                                promise.then(function () {
                                    removeSelectedRows($event);
                                });
                            } else {
                                removeSelectedRows($event);
                            }
                            self.appScope.$emit('REMOVE_ROWS', selectedRows);
                        };
                    });
                    watchers.push(watcher);
                } else if (angular.isFunction(self.options.removeSelectedRows)) {
                    $scope.removeSelectedButtonClick = function ($event) {
                        var promise, selectedRows = getSelectedRows();
                        if (!selectedRows || selectedRows.length == 0) {
                            modalService.openErrorDialogs({
                                messages: ['title.dialogs.info.norecsel']
                            });
                            return false;
                        }
                        promise = self.options.removeSelectedRows();
                        if (promise && angular.isFunction(promise.then)) {
                            promise.then(function () {
                                removeSelectedRows($event);
                            });
                        } else {
                            removeSelectedRows($event);
                        }
                        self.appScope.$emit('REMOVE_ROWS', selectedRows);
                    };
                } else {
                    $scope.removeSelectedButtonClick = function ($event) {
                        var selectedRows = getSelectedRows();
                        if (!selectedRows || selectedRows.length == 0) {
                            modalService.openErrorDialogs({
                                messages: ['title.dialogs.info.norecsel']
                            });
                            return false;
                        }
                        removeSelectedRows($event);
                        self.appScope.$emit('REMOVE_ROWS', selectedRows);
                    }
                }

                $scope.disableElement = function ($event) {
                    var btn = ($event.srcElement || $event.target).parentElement;
                    if (btn.disabled) {
                        return false;
                    }
                    btn.disabled = true;
                    $timeout(function () {
                        btn.disabled = false;
                    }, 1000);
                };

                function removeAllRows($event) {
                    var rows = getAllRows();
                    angular.forEach(rows, function (row) {
                        if (row !== null && row.isSelected) {
                            uiGridSelectionService.toggleRowSelection(self, row, $event, self.options.multiSelect, self.options.noUnselect);
                        }
                    });
                    angular.forEach(rows, function (row) {
                        removeItem(self.options.data, row.entity);
                    });
                    return rows;
                }

                function removeSelectedRows($event) {
                    var selectedRows = getSelectedRows();
                    angular.forEach(selectedRows, function (row) {
                        if (row !== null && row.isSelected) {
                            uiGridSelectionService.toggleRowSelection(self, row, $event, self.options.multiSelect, self.options.noUnselect);
                        }
                    });
                    angular.forEach(selectedRows, function (selectedRow) {
                        removeItem(self.options.data, selectedRow.entity);
                    });
                    return selectedRows;
                }

                function _addRow(data, row) {
                    var scope;
                    if (angular.isString(self.options.data)) {
                        if (self.options.data.match(/ngModel\..*/)) {
                            scope = getNgModelScope($scope);
                        } else {
                            scope = self.appScope;
                        }
                        data = scope.$eval(self.options.data);
                    }
                    data.push(row);
                    sort(data, self);
                    return row;
                }

                function sort(data, grid) {
                    var columnSettings = uiGridGroupingService.getGrouping(grid);
                    columnSettings.grouping.reverse();
                    columnSettings.grouping.forEach(function (groupItem, index) {
                        data.sort(function (a, b) {
                            if (a[groupItem.field] != null && a[groupItem.field] != undefined) {
                                return a[groupItem.field].localeCompare(b[groupItem.field]);
                            } else if (b[groupItem.field] != null && b[groupItem.field] != undefined) {
                                return -1;
                            } else {
                                return 0;
                            }
                        });
                    });
                }

                function getSelectedRows() {
                    if (self._selectedRows) {
                        return self._selectedRows;
                    } else {
                        return self.rows.filter(function (row) {
                            return row.isSelected;
                        });
                    }
                }

                function getAllRows() {
                    return self.rows;
                }

                function removeItem(data, item) {
                    var scope, items;
                    if (angular.isString(self.options.data)) {
                        if (self.options.data.match(/ngModel\..*/)) {
                            scope = getNgModelScope($scope);
                        } else {
                            scope = self.appScope;
                        }
                        items = scope.$eval(self.options.data);
                    } else {
                        items = data;
                    }
                    angular.forEach(items, function (row, index) {
                        if (self.options.rowEquality(row, item) || (row.primaryKey == item.primaryKey && item.primaryKey != undefined)) {
                            if (!(row && row.dataStatus) || 'C' == row.dataStatus) {
                                items.splice(index, 1);
                            } else {
                                items[index].dataStatus = 'D';
                            }
                        }
                    });
                }
                function getNgModelScope(scope) {
                    if (!scope) {
                        return null;
                    }
                    if (scope.hasOwnProperty('ngModel')) {
                        return scope;
                    } else {
                        return getNgModelScope(scope.$parent);
                    }
                }
            }
        };
    }

    uiGridOperationTemplates.$inject = ['$templateCache', 'rowSorter'];
    function uiGridOperationTemplates($templateCache, rowSorter) {
        'use strict';
        if (!rowSorter.guessSortFnOveride) {
            rowSorter.guessSortFn = function guessSortFn(itemType) {
                switch (itemType) {
                    case "number":
                        return rowSorter.sortNumber;
                    case "numberStr":
                        return rowSorter.sortNumberStr;
                    case "boolean":
                        return rowSorter.sortBool;
                    case "string":
                        return rowSorter.sortAlpha;
                    case "date":
                        return rowSorter.sortDate;
                    case "object":
                        return rowSorter.basicSort;
                    default:
                        return rowSorter.sortAlpha;
                }
            };
            rowSorter.guessSortFnOveride = true;
        }
        $templateCache.put('fs/layout/template/uiGrid/tooltipTpl.html', ''
            + '<ul class="fstooltip list-inline">\n'
            + '   <li ng-repeat="message in (row.compareResult.fields[col.colDef.model].tooltip || col.colDef.tooltip)">{{message | translate }}</li>\n'
            + '</ul>\n'
        );

        $templateCache.put('fs-grid/uiGridCell/tooltip', ''
            + '<ul class="list-inline">\n'
            + '    <li ng-repeat="message in tooltipMessage"><span>{{ message | translate }}</span>\n'
            + '</ul>\n'
        );


        $templateCache.put('pti/operationRowHeader', ''
            + '<div class="ui-grid-disable-operation">'
            + '    <div class="ui-grid-cell-contents operationRowHeader">'
            + '        <ui-grid-operation-row-header-buttons></ui-grid-operation-row-header-buttons>'
            + '    </div>'
            + '</div>');

        $templateCache.put('pti/operationRowHeaderButtons', ''
            + '<div class="operationRowHeaderButtons">'
            + '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationView && !(filterRowOperation(row, \'view\') == true)" ng-click="viewRowTooltipIsOpen=false;disableElement($event);viewButtonClick(row, $event)"'
            + '         tooltip-is-open="viewRowTooltipIsOpen" uib-tooltip="{{\'label.global.view\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-view"></span>'
            + '    </button>'
            + '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationEdit && !(filterRowOperation(row, \'edit\') == true)" ng-click="editRowTooltipIsOpen=false;disableElement($event);editButtonClick(row, $event)"'
            + '         tooltip-is-open="editRowTooltipIsOpen" uib-tooltip="{{\'label.global.edit\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-edit"></span>'
            + '    </button>'
            + '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationAddSubRow && !(filterRowOperation(row, \'add\') == true)" ng-click="addSubRowTooltipIsOpen=false;disableElement($event);addSubRowButtonClick(row, $event)"'
            + '        tooltip-is-open="addSubRowTooltipIsOpen" uib-tooltip="{{\'label.global.addsubrow\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-add_1"></span>'
            + '    </button>'
            + '    <button type="button" class="btn btn-default btn-xs" ng-show="!grid.options.enableRowHeaderSelection && grid.options.enableOperationRemove && !(filterRowOperation(row, \'remove\') == true)" ng-click="removeRowTooltipIsOpen=false;disableElement($event);removeButtonClick(row, $event)"'
            + '        tooltip-is-open="removeRowTooltipIsOpen" uib-tooltip="{{\'label.global.remove\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-delete_1"></span>'
            + '    </button>'
            + '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationProcess && !(filterRowOperation(row, \'process\') == true)" ng-click="processRowTooltipIsOpen=false;disableElement($event);processButtonClick(row, $event)"'
            + '        tooltip-is-open="processRowTooltipIsOpen" uib-tooltip="{{\'label.global.process\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-play"></span>'
            + '    </button>'
            + '    <div uib-dropdown dropdown-append-to-body="\'true\'" ng-show="grid.options.enableOperationMoreProcess && !(filterRowOperation(row, \'more\') == true)" style="display:inline-block">'
            + '      <button uib-dropdown-toggle type="button" class="btn btn-default btn-xs" ng-click="moreProcessRowTooltipIsOpen=false;disableElement($event);moreProcessButtonClick(row, $event)"'
            + '        tooltip-is-open="moreProcessRowTooltipIsOpen" uib-tooltip="{{grid.options.moreProcess.tooltip || \'label.global.processmore\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.moreProcess.icon || \'more\'}}"></span>'
            + '      </button>'
            + '      <ul class="animated fadeInUp dropdown-menu-right" uib-dropdown-menu>'
            + '        <li ng-repeat="processConfig in grid.options.moreProcess.items" fs-permission="permission" ng-init="moreProcessPermission(processConfig)" ng-show="!(filterRowOperation(row, processConfig.name) == true)"><a href="#" ng-click="moreProcessClick(row, $event)"><i class="icon icon-{{processConfig.icon}}"></i><span>{{processConfig.label|translate}}</span></a></li>'
            + '      </ul>'
            + '    <div>'
            + '</div>');

        $templateCache.put('pti/eolOperationRowHeader', ''
            + '<div class="ui-grid-disable-operation">'
            + '    <div class="ui-grid-cell-contents operationRowHeader">'
            + '        <ui-grid-operation-row-header-buttons eol></ui-grid-operation-row-header-buttons>'
            + '    </div>'
            + '</div>');

        $templateCache.put('pti/eolOperationRowHeaderButtons', ''
            + '<div class="operationRowHeaderButtons">'
            + '    <button type="button" fs-permission="viewPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationView && !(filterRowOperation(row, \'view\') == true)" ng-click="viewRowTooltipIsOpen=false;disableElement($event);viewButtonClick(row, $event)"'
            + '         tooltip-is-open="viewRowTooltipIsOpen" uib-tooltip="{{grid.options.viewRowByEol.tooltip || (\'label.global.view\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.viewRowByEol.icon || \'view\'}}"></span>'
            + '    </button>'
            + '    <button type="button" fs-permission="editPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationEdit && !(filterRowOperation(row, \'edit\') == true)" ng-click="editRowTooltipIsOpen=false;disableElement($event);editButtonClick(row, $event)"'
            + '         tooltip-is-open="editRowTooltipIsOpen" uib-tooltip="{{grid.options.editRowByEol.tooltip || (\'label.global.edit\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.editRowByEol.icon || \'edit\'}}"></span>'
            + '    </button>'
            + '    <button type="button" fs-permission="cancelPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationCancel && !(filterRowOperation(row, \'cancel\') == true)" ng-click="cancelRowTooltipIsOpen=false;disableElement($event);cancelButtonClick(row, $event)"'
            + '         tooltip-is-open="cancelRowTooltipIsOpen" uib-tooltip="{{grid.options.cancelRowByEol.tooltip || (\'label.global.cancel\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.cancelRowByEol.icon || \'cancel\'}}"></span>'
            + '    </button>'
            + '    <button type="button" fs-permission="downloadPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationDownload && !(filterRowOperation(row, \'download\') == true)" ng-click="downloadRowTooltipIsOpen=false;disableElement($event);downloadButtonClick(row, $event)"'
            + '         tooltip-is-open="downloadRowTooltipIsOpen" uib-tooltip="{{grid.options.downloadRowByEol.tooltip || (\'label.global.download\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.downloadRowByEol.icon || \'download\'}}"></span>'
            + '    </button>'
            + '    <button type="button" fs-permission="addSubPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationAddSubRow && !(filterRowOperation(row, \'add\') == true)" ng-click="addSubRowTooltipIsOpen=false;disableElement($event);addSubRowButtonClick(row, $event)"'
            + '        tooltip-is-open="addSubRowTooltipIsOpen" uib-tooltip="{{grid.options.addSubRowByEol.tooltip || (\'label.global.addsubrow\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.addSubRowByEol.icon || \'add_1\'}}"></span>'
            + '    </button>'
            + '    <button type="button" fs-permission="removePermission" class="btn btn-default btn-xs" ng-show="!grid.options.enableRowHeaderSelection && grid.options.enableEolOperationRemove && !(filterRowOperation(row, \'remove\') == true)" ng-click="removeRowTooltipIsOpen=false;disableElement($event);removeButtonClick(row, $event)"'
            + '        tooltip-is-open="removeRowTooltipIsOpen" uib-tooltip="{{grid.options.removeRowByEol.tooltip || (\'label.global.remove\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.removeRowByEol.icon || \'remove\'}}"></span>'
            + '    </button>'
            + '    <button type="button" fs-permission="processPermission" class="btn btn-default btn-xs" ng-show="grid.options.enableEolOperationProcess && !(filterRowOperation(row, \'process\') == true)" ng-click="processRowTooltipIsOpen=false;disableElement($event);processButtonClick(row, $event)"'
            + '        tooltip-is-open="processRowTooltipIsOpen" uib-tooltip="{{grid.options.processRowByEol.tooltip || (\'label.global.process\'|translate)}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.processRowByEol.icon || \'play\'}}"></span>'
            + '    </button>'
            + '    <div uib-dropdown dropdown-append-to-body="\'true\'" ng-show="grid.options.enableEolOperationMoreProcess && !(filterRowOperation(row, \'more\') == true)" style="display:inline-block">'
            + '      <button uib-dropdown-toggle type="button" class="btn btn-default btn-xs" ng-click="moreProcessRowTooltipIsOpen=false;disableElement($event);moreProcessButtonClick(row, $event)"'
            + '        tooltip-is-open="moreProcessRowTooltipIsOpen" uib-tooltip="{{grid.options.moreProcessByEol.tooltip || \'label.global.processmore\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-{{grid.options.moreProcessByEol.icon || \'more\'}}"></span>'
            + '      </button>'
            + '      <ul class="animated fadeInUp dropdown-menu-right" uib-dropdown-menu>'
            + '        <li ng-repeat="processConfig in grid.options.moreProcessByEol.items" fs-permission="moreProcessPermission(processConfig)" ng-show="!(filterRowOperation(row, processConfig.name) == true)"><a href="#" ng-click="moreProcessClick(row, processConfig, $event)"><i class="icon icon-{{processConfig.icon}}"></i><span>{{processConfig.label|translate}}</span></a></li>'
            + '      </ul>'
            + '    <div>'
            + '</div>');

        $templateCache.put('pti/operationHeaderCell', ''
            + '<div class="operationHeaderCell">'
            + '    <div class="ui-grid-cell-contents operationHeaderCell" col-index="renderIndex">'
            + '        <ui-grid-operation-header-buttons></ui-grid-operation-add-button>'
            + '    </div>'
            + '</div>');

        $templateCache.put('pti/operationHeaderButtons', ''
            + '<div class="operationHeaderButtons">'
            //		+ '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationAdd" ng-click="addTooltipIsOpen=false;disableElement($event);addButtonClick($event)"'
            //		+ '        tooltip-is-open="addTooltipIsOpen" uib-tooltip="{{\'label.global.add\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            //		+ '    	   <span class="icon icon-add_1"></span>'
            //		+ '    </button>'
            + '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationRemoveAll" ng-click="removeAllTooltipIsOpen=false;disableElement($event);removeAllButtonClick($event)"'
            + '        tooltip-is-open="removeAllTooltipIsOpen" uib-tooltip="{{\'label.global.removeselected\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-delete_1"></span>'
            + '    </button>'
            + '    <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableRowHeaderSelection && grid.options.enableOperationRemoveSelected" ng-click="removeTooltipIsOpen=false;disableElement($event);removeSelectedButtonClick($event)"'
            + '        tooltip-is-open="removeTooltipIsOpen" uib-tooltip="{{\'label.global.removeselected\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	   <span class="icon icon-delete_1"></span>'
            + '    </button>'
            + '</div>');

        $templateCache.put('ui-grid/ui-grid-grid-footer',
            "<div class=\"ui-grid-footer-info ui-grid-grid-footer\"><span>{{\"label.pagination.totalitems\"|translate}}: {{grid.options.totalItems}}</span> <span ng-if=\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\" class=\"ngLabel\">({{\"search.showingItems\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>"
        );

        $templateCache.put('ui-grid/gridFooterSelectedItems',
            "<span ng-if=\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\">({{\"label.pagination.selecteditems\"|translate}}: {{grid.selection.selectedCount}})</span>"
        );

        $templateCache.put('ui-grid/pagination', ''
            + '<div role="contentinfo" class="ui-grid-pager-panel paginationBar clearfix" ui-grid-pager ng-if="grid.options.enablePaginationControls">'
            + '    <ul class="pull-right" uib-pagination template-url="ui-grid/pagination/pagination.html" items-per-page="grid.options.paginationPageSize" total-items="grid.options.totalItems" ng-model="grid.options.paginationCurrentPage" boundary-links="true" first-text="<<" previous-text="<" next-text=">" last-text=">>"></ul>'
            + '    <div class="pagination ui-grid-pager-row-count-picker pull-right" ng-if="grid.options.paginationPageSizes.length > 1 && !grid.options.useCustomPagination">'
            + '       <label> {{"label.pagination.go"|translate}} </label> <input type="number" onclick="this.focus()" class="form-control input-sm btn-xs" ui-grid-one-bind-title="aria.pageSelected" ui-grid-one-bind-aria-label="aria.pageSelected" class="ui-grid-pager-control-input" ng-model="grid.options.paginationCurrentPage" ng-keydown="grid.options.pageNumKeydown()" ng-model-options="{ updateOn: \'blur\' }" style="width:60px" min="1" max="{{ paginationApi.getTotalPages() }}" required>'
            + '       <span class="ui-grid-pager-max-pages-number" ng-show="paginationApi.getTotalPages() > 0">/ {{ paginationApi.getTotalPages() }}</span>'
            + '    </div>'
            + '    <div class="pagination ui-grid-pager-row-count-picker pull-right" ng-if="grid.options.paginationPageSizes.length > 1 && !grid.options.useCustomPagination">'
            + '       <label style="padding-right:8px;">{{grid.options.totalItems}} {{\"label.pagination.totalitems\"|translate}} </label>  <label> {{"label.pagination.pagesize"|translate}} </label> <select class="form-control input-sm btn-xs" ui-grid-one-bind-aria-labelledby-grid="\'items-per-page-label\'" ng-model="grid.options.paginationPageSize" ng-options="o as o for o in grid.options.paginationPageSizes"></select>'
            + '    </div>'
            + '</div>'
        );

        $templateCache.put('ui-grid/pagination/pagination.html', ''
            + '<li ng-if="::boundaryLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-first"><a href ng-click="selectPage(1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle><span class="icon icon-firstpage"></span></a></li>\n'
            + '<li ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev"><a href ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle><span class="icon icon-page-left"></span></a></li>\n'
            + '<li ng-if="page > 6" class="pagination-page disabled"><a href uib-tabindex-toggle>...</a></li>\n'
            + '<li ng-repeat="pageItem in pages track by $index" ng-class="{active: pageItem.active,disabled: ngDisabled&&!pageItem.active}" class="pagination-page">'
            + '  <a href ng-click="selectPage(pageItem.number, $event)" ng-if="(pageItem.number <= page + 5) && (pageItem.number >= page - 5)" ng-disabled="ngDisabled&&!pageItem.active" uib-tabindex-toggle>{{pageItem.text}}</a>'
            + '</li>\n'
            + '<li ng-if="page < pages.length - 5" class="pagination-page disabled"><a href uib-tabindex-toggle>...</a></li>\n'
            + '<li ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next"><a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle><span class="icon icon-page-right"></span></a></li>\n'
            + '<li ng-if="::boundaryLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-last"><a href ng-click="selectPage(totalPages, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle><span class="icon icon-lastpage"></span></a></li>\n'
        );

        $templateCache.put('ui-grid/selectionRowHeaderButtons', ''
            + '<div class="selectionRowHeaderButtons">'
            + '    <input class="rowHeader" type="{{grid.options.multiSelect ? \'checkbox\' : \'radio\'}}" id="{{grid.id}}" ng-if="!row.groupHeader" ng-disabled="!grid.options.isRowSelectable(row)" ng-checked="row.isSelected" ng-click="selectButtonClick(row, $event)"><label ng-if="!row.groupHeader" for="{{row.uid}}">&nbsp;</label>'
            + '</div>'
        );

        $templateCache.put('ui-grid/selectionSelectAllButtons', ''
            + '<div class="selectionSelectAllButtons">'
            + '    <input type="checkbox" id="{{grid.id}}" ng-show="grid.options.multiSelect" ng-checked="grid.selection.selectAll" ng-click="headerButtonClick($event)"><label ng-show="grid.options.multiSelect" for="{{grid.id}}">&nbsp;</label>'
            + '</div>'
        );

        $templateCache.put('ui-grid/ui-grid-header', ""
            + "<div role=\"rowgroup\" class=\"ui-grid-header\">\n"
            + " <!-- theader -->\n"
            + " <div class=\"ui-grid-top-panel\">\n"
            + "   <div class=\"ui-grid-header-viewport\">\n"
            + "     <div class=\"ui-grid-header-canvas\">\n"
            + "       <div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\">\n"
            + "         <div role=\"row\" class=\"ui-grid-header-cell-row\">\n"
            + "           <div class=\"ui-grid-header-cell ui-grid-clearfix\" ng-mouseover=\"col.colDef._hover=true\" ng-mouseleave=\"col.colDef._hover=false\" ng-class=\"{'hover': col.colDef._hover}\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" ui-grid-header-cell col=\"col\" render-index=\"$index\"></div>\n"
            + "           </div>\n"
            + "         </div>\n"
            + "       </div>\n"
            + "   </div>\n"
            + " </div>\n"
            + "</div>");

        $templateCache.put('ui-grid/uiGridHeaderCell', ""
            + "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable, 'ui-grid-header-cell-last-col': isLastCol }\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\">\n"
            + "    <div role=\"button\" tabindex=\"0\" ng-keydown=\"handleKeyDown($event)\" ng-mouseover=\"col.colDef._hover=true\" ng-mouseleave=\"col.colDef._hover=false\" ng-class=\"{'text-right':col.colDef.textAlign == 'right', 'text-left':col.colDef.textAlign == 'left', 'text-center':col.colDef.textAlign == 'center', 'hover': col.colDef._hover}\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\">\n"
            + "        <span ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">\n"
            + "            <span ng-if=\"col.colDef.isRequired\" ng-class=\"{required: col.colDef.isRequired}\" style=\"padding-right:2px\"></span> <span>{{ col.displayName CUSTOM_FILTERS }}</span>\n"
            + "        </span>\n"
            + "    </div>\n"
            + "    <div style=\"top: 0; width: 16px; position: absolute; right: 0; line-height: 6px;padding-top: 8px;\" ng-if=\"col.sort.direction\">\n"
            + "         <i class=\"icon icon-up_1\" ng-class=\"{ 'active': col.sort.direction == asc, 'disable': !col.sort.direction }\" aria-hidden=\"true\"></i> \n"
            + "         <i class=\"icon icon-down_1\" ng-class=\"{ 'active': col.sort.direction == desc, 'disable': !col.sort.direction }\" aria-hidden=\"true\"></i> \n"
            + "    </div>\n"
            + "    <div role=\"button\" tabindex=\"0\" ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader  && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-keydown=\"headerCellArrowKeyDown($event)\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\">\n"
            + "        <i class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i>\n"
            + "    </div>\n"
            + "    <div ui-grid-filter></div>\n"
            + "</div>"
        );

        $templateCache.put('ui-grid/uiGridViewport', ''
            + '<div role="rowgroup" class="ui-grid-viewport" ng-style="colContainer.getViewportStyle()">\n'
            + '<div ui-grid-customer-scrollbar on-scroll="scrollHandler" refresh-on-change="rowContainer.renderedRows" wheel-propagation="true" class="scroller">\n'
            + "    <!-- tbody -->\n"
            + '    <div class="ui-grid-canvas">\n'
            + '        <div ng-form="rowForm{{side ? rowRenderIndex : \'Entity\'+rowRenderIndex}}" ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows" class="ui-grid-row" ng-style="Viewport.rowStyle(rowRenderIndex)">'
            + '            <div role="row" class="grid-row" ui-grid-row="row" ng-mouseover="row._hover=true" ng-mouseleave="row._hover=false"'
            + '                ng-class="{\'selected-row\':row.isSelected,'
            + '                           \'hover-row\':row._hover, '
            + '                           \'created-row\':row.compareResult.isCreated,'
            + '                           \'deleted-row\':row.compareResult.isDeleted,'
            + '                           \'updated-row\':row.compareResult.isUpdated}" row-render-index="rowRenderIndex" '
            + '                fs-ui-grid-compare="row.grid.options.verifyData" fs-ui-grid="grid" fs-ui-grid-row="row" fs-ui-grid-col="col"></div>'
            + '         </div>'
            + '    </div>'
            + '</div>'
            + '</div>'
        );

        $templateCache.put('ui-grid/uiGridCell', ''
            + '<div class="ui-grid-cell-contents" ng-class="{\'updated-cell\': row.compareResult.fields[col.colDef.model].hasChanged}" title="TOOLTIP"'
            + '  ng-style="{\'text-align\':col.colDef.textAlign || \'left\'}"'
            + '  uib-tooltip-template="\'fs/layout/template/uiGrid/tooltipTpl.html\'"'
            + '  tooltip-enable="(row.compareResult.columns[col.colDef.model].tooltipMessage && row.compareResult.columns[col.colDef.model].tooltipMessage.length > 0) || (col.colDef.tooltip && col.colDef.tooltip.length > 0)"'
            + '  tooltip-class="{{col.colDef.tooltipClass}}" '
            + '  tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="true" '
            + '  tooltip-placement="{{col.colDef.tooltipPlacement}}">'
            + '    <span>{{COL_FIELD CUSTOM_FILTERS}}</span>'
            + ' </div>'
        );

        $templateCache.put('ui-grid/ui-grid', ""
            + "<div ui-i18n=\"en\" class=\"ui-grid\" ng-class=\"{'enable-grid-menu':grid.options.enableGridMenu}\"><!-- TODO (c0bra): add \"scoped\" attr here, eventually? -->\n"
            + "    <style ui-grid-style>\n"
            + "    .grid{{ grid.id }} {\n"
            + "        /* Styles for the grid */\n"
            + "    }\n" +
            + "    .grid{{ grid.id }} .ui-grid-row, \n"
            + "    .grid{{ grid.id }} .ui-grid-cell, \n"
            + "    .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\n"
            + "        min-height: {{ grid.options.rowHeight }}px;\n"
            + "    }\n"
            + "    .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\n"
            + "        border-bottom-width: {{ (((grid.getVisibleRowCount() * grid.options.rowHeight) < grid.getViewportHeight()) && '1px') || '0' }};\n"
            + "    }\n"
            + "\n"
            + "    {{ grid.verticalScrollbarStyles }}\n"
            + "    {{ grid.horizontalScrollbarStyles }}\n"
            + "\n"
            + "    /*\n"
            + "    .ui-grid[dir=rtl] .ui-grid-viewport {\n"
            + "        padding-left: {{ grid.verticalScrollbarWidth }}px;\n"
            + "    }\n"
            + "    */\n"
            + "    \n"
            + "    {{ grid.customStyles }}\n"
            + "\n"
            + "    </style>\n"
            + "    <div class=\"ui-grid-contents-wrapper\" role=\"grid\">\n"
            + "        <div ui-grid-menu-customer-button ng-if=\"grid.options.enableGridMenu\"></div>\n"
            + "        <div ng-if=\"grid.hasLeftContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'left'\" class=\"oprationContainer\"></div>\n"
            + "        <div ui-grid-render-container container-id=\"'body'\" col-container-name=\"'body'\" row-container-name=\"'body'\" bind-scroll-horizontal=\"true\" bind-scroll-vertical=\"true\"\n"
            + "            enable-horizontal-scrollbar=\"grid.options.enableHorizontalScrollbar\" \n"
            + "            enable-vertical-scrollbar=\"grid.options.enableVerticalScrollbar\"></div>\n"
            + "        <div ng-if=\"grid.hasRightContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'right'\" class=\"oprationContainer\"></div>\n"
            + "        <div ui-grid-grid-footer ng-if=\"grid.options.showGridFooter\" class=\"gridFooterbox clearfix\"></div>\n"
            + "        <div ui-grid-column-menu ng-if=\"grid.options.enableColumnMenus\" style=\"z-index:1000\"></div>\n"
            + "        <div ng-transclude></div>\n"
            + "    </div>\n"
            + "</div>"
        );

        $templateCache.put('ui-grid/ui-grid-menu-button', ""
            + "<div class=\"ui-grid-menu-button\">\n"
            + "  <div class=\"media\">\n"
            + "    <div class=\"switch media-body media-middle\">"
            + "      <input type=\"checkbox\" id=\"switch{{grid.id}}\" ng-model=\"switchChecked\" class=\"switch-checkbox\" ng-checked=\"grid.options.displayStyle == 'all'\" ng-click=\"toggleDisplayStyle()\">"
            + "      <label class=\"switch-label\" for=\"switch{{grid.id}}\">"
            + "        <span class=\"switch-inner\" data-all=\"{{'grid.label.showall' | translate}}\" data-normal=\"{{'grid.label.normal' | translate}}\"></span>"
            + "        <span class=\"switch-icon\"></span>"
            + "      </label>"
            + "    </div>"
            + "    <div role=\"button\" ui-grid-one-bind-id-grid=\"'grid-menu'\" class=\"ui-grid-icon-container media-right media-middle\" ng-click=\"toggleMenu()\" aria-haspopup=\"true\">\n"
            + "        <i class=\"ui-grid-icon-menu\"></i>\n"
            + "    </div>\n"
            + "  </div>"
            + "  <div ui-grid-menu menu-items=\"menuItems\"></div>\n"
            + "</div>"
        );

        $templateCache.put('ui-grid/uiGridMenu', ""
            + "<div class=\"ui-grid-menu\" ng-show=\"shown\">\n"
            /*+ "    <style ui-grid-style>{{dynamicStyles}}</style>\n"*/
            + "    <div class=\"ui-grid-menu-mid\" ng-show=\"shownMid\">\n"
            + "        <div class=\"ui-grid-menu-inner\" ng-if=\"shown\">\n"
            + "            <ul role=\"menu\" class=\"ui-grid-menu-items\">\n"
            + "                <li><h4>{{'grid.label.customize'|translate}}:</h4></li>\n"
            + "                <li ng-repeat=\"item in menuItems\" ng-click=\"$event.stopPropagation();\" ng-if=\"item.context && item.context.gridCol\" role=\"menuitem\" ui-grid-customer-menu-item ui-grid-one-bind-id=\"'menuitem-'+$index\"action=\"item.action\" name=\"item.title\" active=\"item.active\" icon=\"item.icon\" shown=\"item.shown\" context=\"item.context\" template-url=\"item.templateUrl\" leave-open=\"item.leaveOpen\" index=\"$index\" screen-reader-only=\"item.screenReaderOnly\"></li>\n"
            + "            </ul>\n"
            + "        </div>\n"
            + "    </div>\n"
            + "</div>"
        );


        $templateCache.put('ui-grid/uiGridMenuItem', ""
            + "<div class=\"ui-grid-menu-item\" ng-focus=\"focus=true\" ng-blur=\"focus=false\" ng-show=\"itemShown() && action\">\n"
            + "    <input id=\"{{getGrid().id+''+index}}\" type=\"checkbox\" ng-model=\"visible\" ng-click=\"itemAction($event, title)\" ng-checked=\"visible != false\"/>"
            + "     <label for=\"{{getGrid().id+''+index}}\" style=\"cursor: pointer;\" >{{ label() }}</label>"
            + "</div>"
        );

        $templateCache.put('ui-grid/uiGridRenderContainer', ""
            + "<div role=\"presentation\" ui-grid-one-bind-id-grid=\"'grid-container'\" class=\"ui-grid-render-container\" ng-style=\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\">\n"
            + "    <!-- All of these dom elements are replaced in place -->\n"
            + "    <div ui-grid-header></div>\n"
            + "    <div ui-grid-viewport></div>\n"
            + "    <div ng-if=\"colContainer.needsHScrollbarPlaceholder()\" class=\"ui-grid-scrollbar-placeholder\" ng-style=\"{height:colContainer.grid.scrollbarHeight + 'px'}\"></div>\n"
            + "    <ui-grid-footer ng-if=\"grid.options.showColumnFooter\"></ui-grid-footer>\n"
            + "</div>");

        $templateCache.put('ui-grid/ui-grid-footer', ""
            + "<div class=\"ui-grid-footer-panel ui-grid-footer-aggregates-row\">\n"
            + "    <!-- tfooter -->\n"
            + "    <div class=\"ui-grid-footer ui-grid-footer-viewport\">\n"
            + "        <div class=\"ui-grid-footer-canvas\">\n"
            + "            <div class=\"ui-grid-footer-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\">\n"
            + "                <div role=\"row\" class=\"ui-grid-footer-cell-row\">\n"
            + "                    <div role=\"gridcell\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" col=\"col\" render-index=\"$index\" class=\"ui-grid-footer-cell ui-grid-clearfix\">\n"
            + "                        <div class=\"operationHeaderButtons\" ng-if=\"col.colDef.name == 'operationRowHeaderCol' && col.grid.options.__addRow\">\n"
            + '                            <button type="button" class="btn btn-default btn-xs" ng-show="grid.options.enableOperationAdd" ng-click="addTooltipIsOpen=false;col.grid.options.__addRow($event)"'
            + '                                tooltip-is-open="addTooltipIsOpen" uib-tooltip="{{\'label.global.add\'|translate}}" tooltip-append-to-body="true" tooltip-trigger="\'mouseenter\'" tooltip-append-to-body="false" tooltip-placement="top">'
            + '    	                           <span class="icon icon-add_1"></span>'
            + '                            </button>'
            + "                         </div>"
            + "                    </div>\n"
            + "                </div>\n"
            + "            </div>\n"
            + "        </div>\n"
            + "    </div>\n"
            + "</div>"
        );

        $templateCache.put('ui-grid/emptyBaseLayerContainer', '');

        $templateCache.put('ui-grid/columnResizer',
            "<div ui-grid-customer-column-resizer ng-if=\"grid.options.enableColumnResizing && !grid.options.disableColumnResize\" class=\"ui-grid-column-resizer\" col=\"col\" position=\"right\" render-index=\"renderIndex\" unselectable=\"on\"></div>"
        );

		/*
		 * $templateCache.put('ui-grid/ui-grid-header', "" + "<div role=\"rowgroup\" class=\"ui-grid-header\">\n" + " <!-- theader -->\n" + " <div class=\"ui-grid-top-panel\">\n" + " <div
		 * class=\"ui-grid-header-viewport\">\n" + " <div class=\"ui-grid-header-canvas\">\n" + " <div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\">\n" + " <div
		 * role=\"row\" class=\"ui-grid-header-cell-row\">\n" + " <div class=\"ui-grid-header-cell ui-grid-clearfix\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" ui-grid-header-cell
		 * col=\"col\" render-index=\"$index\"></div>\n" + " </div>\n" + " </div>\n" + " </div>\n" + " </div>\n" + " </div>\n" + "</div>" );
		 * 
		 * $templateCache.put('ui-grid/uiGridHeaderCell', "" + "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable, 'ui-grid-header-cell-last-col': isLastCol }\"
		 * ui-grid-one-bind-aria-labelledby-grid=\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ?
		 * 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\">\n" + " <div role=\"button\" tabindex=\"0\" ng-keydown=\"handleKeyDown($event)\" class=\"ui-grid-cell-contents
		 * ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\">\n" + " <span class=\"ui-grid-header-cell-label\" ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">{{
		 * col.displayName CUSTOM_FILTERS }}</span> \n" + " <span ui-grid-one-bind-id-grid=\"col.uid + '-sortdir-text'\" ui-grid-visible=\"col.sort.direction\"
		 * aria-label=\"{{getSortDirectionAriaLabel()}}\">\n" + " <i ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc,
		 * 'ui-grid-icon-blank': !col.sort.direction }\" title=\"{{isSortPriorityVisible() ? i18n.headerCell.priority + ' ' + ( col.sort.priority + 1 ) : null}}\" aria-hidden=\"true\"></i> \n" + " <sub
		 * ui-grid-visible=\"isSortPriorityVisible()\" class=\"ui-grid-sort-priority-number\">{{col.sort.priority + 1}}</sub>\n" + " </span>\n" + " </div>\n" + " <div role=\"button\" tabindex=\"0\"
		 * ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false\"
		 * ng-click=\"toggleMenu($event)\" ng-keydown=\"headerCellArrowKeyDown($event)\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\">\n" + " <i
		 * class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i>\n" + " </div>\n" + " <div ui-grid-filter></div>\n" + "</div>" );
		 * 
		 * $templateCache.put('ui-grid/ui-grid-row', "" + "<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\"" + " ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' +
		 * col.uid + '-cell'\" class=\"ui-grid-cell\"" + " ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" " + " role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\"" + " ui-grid-cell>\n" +"</div>" );
		 */
    }
})(angular);